LDAP
Configure ODD Platform to authenticate users against an existing LDAP server, including group-to-role mapping and the cross-mode user-name collision caveat for multi-mode deployments.
ODD Platform can be configured to use existing LDAP server for users authentication. There are several properties, that need to be set in order to enable this kind of security.
Define authentication type
auth:
type: LDAPAUTH_TYPE=LDAPConnect to LDAP server
There are 3 properties, which are responsible for connecting to LDAP server
auth.ldap.url: LDAP server url (required)auth.ldap.username: The username (principal) to use when authenticating with the LDAP serverauth.ldap.password: The password (credentials) to use when authenticating with the LDAP server
Username and password are not required. If they are not set, operations will be performed by using an anonymous (unauthenticated) context
auth:
ldap:
url: "ldap://localhost:389"
username: admin
password: passwordAUTH_LDAP_URL=ldap://localhost:389
AUTH_LDAP_USERNAME=admin
AUTH_LDAP_PASSWORD=passwordUse ldaps:// for any server reachable beyond localhost. The platform passes auth.ldap.url to the LDAP client exactly as written and does not enforce a scheme. With an ldap:// URL — including the ldap://localhost:389 example above — the bind credentials and every end user's login password travel to the directory in cleartext. No warning is logged at startup. Set the URL to ldaps://your-server:636 unless the directory is on the same host as the platform.
auth.ldap.password is held in plaintext. The bind password is read straight from configuration and kept as a plain string in the running process; it is not encrypted and is not redacted from the platform's own configuration view. Treat it as a secret at rest: supply it through your deployment's secret mechanism rather than committing it to a values file, and restrict who can read the platform's environment and configuration.
Perform users search
There are 2 ways of how to retrieve users in LDAP server.
Define DN pattern of user names. This is great, when all users are stored under a single node in a directory.
Setup LDAP search filter.
DN pattern
This is an example of how user DN pattern can be defined. In this case DN for the user will be built by substituting login in the supplied pattern instead of 0.
Search filter
This is an example of using search filter instead of DN pattern. If a user search base isn’t supplied, the search will be performed from the root.
DN pattern
This is an example of how user DN pattern can be defined. In this case DN for the user will be built by substituting login in the supplied pattern
Search filter
This is an example of using search filter instead of DN pattern. If a user search base isn’t supplied, the search will be performed from the root.
It is required to set up one of those search methods, otherwise application start will fail
Define admin groups
ODD platform can get LDAP groups, which the user belongs to. Thus it is possible to define which groups will grant admin privileges. There are several properties that need to be set in order to allow ODD platform to do this:
auth.ldap.groups.search-base: The base DN from which the search for group membership should be performed. By default it will be performed from the root.auth.ldap.groups.filter: The pattern used to find the groups a user belongs to. ODD platform does not set this default itself — when you leave it unset, the platform never overrides the group search filter, and Spring Security'sDefaultLdapAuthoritiesPopulatorapplies its own built-in default of(member={0}), where the user's DN is substituted for{0}.auth.ldap.groups.admin-groups: List of groups, which members will be granted admin permissions.
Active directory
If you are using Active Directory as LDAP server there are additional properties, that need to be set
auth.ldap.active-directory.enabled: Must be set totrueauth.ldap.active-directory.domain: Domain name
Set domain whenever you set enabled: true. The platform does not check that the two go together: a configuration with active-directory.enabled: true and no domain starts up without an error and then attempts Active Directory binds with no domain, which fail at sign-in time rather than at startup. Always provide both values together.
Final configuration example
Admin promotion (group-name matching)
For the cross-mode comparison of how every auth mode and OAuth provider grants ADMIN, see Admin promotion across providers. The notes below cover LDAP-specific behaviour only.
auth.ldap.groups.admin-groups accepts a list of group names whose members the platform promotes to ADMIN. A user is promoted when one of their LDAP group names equals a configured value, compared case-insensitively on the whole name. The comparison is not a substring or prefix match: each configured token must match an entire group name, ignoring only letter case.
admin-groups value
LDAP group the user belongs to
Promoted to ADMIN?
Admin
Admin
Yes — same name
Admin
admin
Yes — case is ignored
Admin
Administrator
No — different name
ops
devops
No — different name
Because matching is whole-name, list every admin group explicitly. Adding ops does not promote members of devops or dataops; if those groups should also be admins, name each of them in admin-groups.
When auth.ldap.groups.admin-groups is empty or unset
If auth.ldap.groups is configured but admin-groups is empty (admin-groups: [] or simply omitted), every authenticated LDAP user is granted the USER role only — there is no path to ADMIN via LDAP under this configuration, and no boot warning surfaces the absence. A deployment that uncomments the LDAP block but forgets the admin-groups entry has no possible ADMIN user via LDAP. Decide on the admin-groups value at the same time you author the rest of the LDAP block, even if your initial value is a single well-known operator group.
A platform-side fix that fail-fast-warns when auth.ldap.groups is configured without admin-groups is tracked upstream.
Cross-mode user-name collision (activity feed read paths)
The platform's activity-feed read paths join the USER_OWNER_MAPPING table on OIDC_USERNAME only — the join does not discriminate by auth provider. If your deployment has historically used multiple auth modes (for example, started on LOGIN_FORM with seed users, then enabled LDAP), a user named alice who signed in via LOGIN_FORM and a user named alice who signed in via LDAP can resolve to the same OwnerPojo when activity-feed rows are rendered. The most recent USER_OWNER_MAPPING row for the literal username wins each lookup; results are not deterministic across replicas.
Operator mitigation today: never reuse usernames across auth modes when migrating. If you migrate from LOGIN_FORM to LDAP, delete the USER_OWNER_MAPPING rows for the LOGIN_FORM usernames before introducing same-named LDAP users.
Forensic note: do not rely on activity-feed Owner attribution for incident response in multi-mode deployments without verifying the auth mode of the actor through the underlying activity.created_by value.
A platform-side fix that discriminates the join by PROVIDER is tracked upstream. The same caveat applies to deployments running LOGIN_FORM on top of an earlier LDAP history — see the matching note on the Login form page.
Last updated