Skip to main content

LDAP

This section describes the LDAP authentication mechanism in Sync-in.

Configuration lives in environment.yaml, see LDAP section.


Authentication flow​

The LDAP flow is:

  1. The user enters their identifier (login or email) and password.
    • Guest accounts and application scopes (app passwords) always use local authentication.
  2. Sync-in prepares the LDAP identifier (UPN or DOMAIN\user for AD) and attempts a bind.
  3. Sync-in reads the authenticated LDAP entry (exact DN for generic direct bind, subtree search for service bind and AD) and its required attributes.
  4. If authentication is valid, Sync-in synchronizes (or creates) the local account.
  5. The administrator role can be assigned via an LDAP group.
  6. If LDAP is unavailable, a local fallback may be allowed for administrators and optionally for regular users (see Break-glass).

Configuration​

Minimal example:

auth:
provider: ldap
ldap:
servers: ['ldap://localhost:389']
baseDN: 'ou=people,dc=ldap,dc=sync-in,dc=com'
attributes:
login: uid
email: mail

Attributes and normalization​

The following attributes are required in the LDAP entry:

  • attributes.login: used for the local login.
  • attributes.email: used for the local email.

attributes.storageQuota is optional and defaults to storageQuota. When present, it is read as a quota in bytes and synchronized to the local account. Invalid values leave the local quota unchanged. An absent value or a value of 0 sets unlimited storage.

The local login is normalized: if the identifier is provided as DOMAIN\user, only user is stored locally.
The memberOf field is normalized into a list of values and CNs, which enables group checks.
If options.adminGroup is set and memberOf is insufficient, Sync-in attempts a targeted groupOfNames lookup for that group.


Service account​

By default, Sync-in attempts a direct bind using the user's credentials.
A service account can be configured to perform LDAP searches:

auth:
ldap:
serviceBindDN: 'cn=syncin,ou=services,dc=ldap,dc=sync-in,dc=com'
serviceBindPassword: 'LDAPServiceBindPasswordToChange'

With a service bind:

  • Initial bind with the service account.
  • User lookup under baseDN with the directory-specific search filter (+ configured filter).
  • Rebind with the found DN and provided password.

Without a service bind:

  • Generic LDAP: Sync-in constructs <attributes.login>=<login>,<baseDN>, escapes the login as an LDAP RDN, binds that DN, then reads that exact entry with base scope.
  • Active Directory: Sync-in binds with the AD login, then searches the entry under baseDN.

For generic LDAP, the optional configured filter also applies to the exact read. A read that succeeds without returning an entry ends authentication. If the directory rejects that read with a known access or compatibility error, Sync-in performs a guarded subtree lookup using only the configured attributes.login (+ filter). The lookup must return exactly one complete, non-truncated result with a DN, and Sync-in binds that DN again with the submitted password before using its attributes. This compatibility path does not run for an empty result or an unrelated technical error.

Use a service account when the user DN cannot be constructed with this formula, or when users cannot search the attributes or groups required by Sync-in.


Active Directory specifics​

If attributes.login is sAMAccountName or userPrincipalName, Sync-in adapts the login:

  • userPrincipalName: a suffix can be added via upnSuffix (e.g. user@sync-in.com).
  • sAMAccountName: a prefix can be added via netbiosName (e.g. SYNC_IN\user).

In this mode, the user bind is done directly with the provided login (UPN or DOMAIN\user format).

Subtree search filters are adapted automatically:

  • AD: (sAMAccountName=...) OR (userPrincipalName=...) OR (mail=...)
  • Generic LDAP with a service bind: (uid=...) OR (cn=...) OR (mail=...)

The normal generic LDAP direct-bind path does not use this OR filter: it reads the authenticated DN itself. Its guarded compatibility lookup matches only the configured attributes.login and requires a unique, non-truncated result followed by a successful bind to that result's DN.


Administrator roles​

If options.adminGroup is set, Sync-in checks group membership:

  • via memberOf if present,
  • otherwise via a groupOfNames search (useful when memberOf is not exposed).

If group lookup is not possible with the user, use a service account.

If options.adminGroup is not set, existing admin accounts keep their role and cannot be demoted via LDAP.


Break-glass (local fallback)​

If LDAP is unavailable (connectivity error, service down), Sync-in can allow local password authentication:

  • Always allowed for administrator accounts (break-glass), even when LDAP auth fails.
  • For other users, allowed only when the failure is tied to LDAP unavailability and options.enablePasswordAuthFallback is enabled.

This mechanism ensures continuity of administrative access when the directory service is unavailable.

For this fallback to be usable, administrator accounts should have a local Sync-in password configured and kept available.

For regular users, this fallback is disabled by default.


Account synchronization​

On successful login:

  • If the user does not exist and autoCreateUser is enabled, Sync-in creates a local account.
  • The local login is derived from attributes.login.
  • The email is derived from attributes.email (required).
  • First/last name are derived from givenName + sn, or displayName, or cn.
  • Initial permissions come from autoCreatePermissions.
  • The storage quota is synchronized from attributes.storageQuota when the LDAP entry provides a valid value in bytes. An absent value or a value of 0 sets unlimited storage.

Availability and errors​

Invalid LDAP credentials reject authentication.
LDAP connectivity errors are treated as service unavailability and may trigger local fallback (see Break-glass).
Guest accounts and application scopes do not use LDAP and always authenticate locally.

Security​

It is strongly recommended to use LDAPS (ldaps://) or StartTLS to protect credentials sent during the LDAP bind.