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:
- The user enters their identifier (login or email) and password.
- Guest accounts and application scopes (app passwords) always use local authentication.
- Sync-in prepares the LDAP identifier (UPN or
DOMAIN\userfor AD) and attempts a bind. - Sync-in reads the authenticated LDAP entry (exact DN for generic direct bind, subtree search for service bind and AD) and its required attributes.
- If authentication is valid, Sync-in synchronizes (or creates) the local account.
- The administrator role can be assigned via an LDAP group.
- 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
baseDNwith the directory-specific search filter (+ configuredfilter). - 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 viaupnSuffix(e.g.user@sync-in.com).sAMAccountName: a prefix can be added vianetbiosName(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
memberOfif present, - otherwise via a
groupOfNamessearch (useful whenmemberOfis 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.enablePasswordAuthFallbackis 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
autoCreateUseris 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, ordisplayName, orcn. - Initial permissions come from
autoCreatePermissions. - The storage quota is synchronized from
attributes.storageQuotawhen the LDAP entry provides a valid value in bytes. An absent value or a value of0sets 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.