Skip to main content
Version: 5.1

LDAP User Store

ICP can authenticate users against an external LDAP directory instead of the built-in credentials database. The LDAP adapter supports standard LDAP servers (OpenLDAP, 389 Directory Server, etc.) and Active Directory.

Prerequisites
  • The LDAP server is reachable from the host running ICP.
  • A service account (bind DN + password) with read access to user and group entries exists, or your LDAP server allows anonymous bind.
  • You know the base DN under which users are stored (e.g. ou=Users,dc=wso2,dc=org).

Configuration​

All LDAP settings are top-level keys in conf/deployment.toml. Only ldapUserStoreEnabled = true is strictly required to activate the adapter; all other keys have defaults.

Step 1: Activate the adapter​

ldapUserStoreEnabled = true
warning

When LDAP is enabled, users in the built-in user store, including the default admin, can no longer sign in. Before switching, make sure at least one LDAP user is a member of a group listed in ldapAdminRoles (see Step 5).

Step 2: Configure the server connection​

ldapHostName = "ldap.example.com"   # default: localhost
ldapPort = 389 # default: 389; use 636 for LDAPS

# Service-account credentials used to search the directory.
# Omit (leave empty) for anonymous bind.
ldapConnectionName = "uid=admin,ou=system"
ldapConnectionPassword = "secret"
KeyDefaultDescription
ldapUserSearchBaseou=Users,dc=wso2,dc=orgBase DN for user searches
ldapUserNameAttributeuidAttribute that holds the login username
ldapUserSearchFilter(&(objectClass=person)(uid=?))Filter to locate a user; ? is replaced with the username
ldapUserDNPattern(empty)Optional shortcut to construct the DN directly without a search (see below)
ldapDisplayNameAttributecnAttribute used as the display name in ICP; set it to empty to use the username

ldapUserDNPattern avoids a search round-trip by constructing the DN from the username directly. Use {0} as the placeholder:

ldapUserDNPattern = "uid={0},ou=Users,dc=wso2,dc=org"

If the pattern is set, ldapUserSearchFilter and the admin bind are not used for authentication (though they are still used for group lookup if ldapMemberOfAttribute is not set).

Step 4: Configure group and role lookup​

ICP reads groups solely to determine whether a user should be granted super-admin access. All other access control is managed through ICP's own user management. Two strategies are supported.

Strategy A: memberOf (Active Directory and some standard LDAP servers)​

The user entry contains a memberOf attribute that lists the DNs of every group the user belongs to. This is the most efficient strategy.

ldapMemberOfAttribute = "memberOf"

When this is set, the group-search settings below are ignored.

Strategy B: Group membership search (standard LDAP)​

ICP searches the group subtree for entries whose membership attribute contains the user's DN.

ldapGroupSearchBase     = "ou=Groups,dc=wso2,dc=org"   # default
ldapGroupNameAttribute = "cn" # default
ldapGroupSearchFilter = "(objectClass=groupOfNames)" # default
ldapMembershipAttribute = "member" # default; or "uniqueMember"

For posixGroup schemas where membership is stored as plain usernames rather than full DNs, set:

ldapMembershipAttribute = "memberUid"

Set ldapReadGroups = false to skip group lookup entirely (no user will receive super-admin via LDAP roles).

Step 5: Configure admin role mapping​

List the LDAP group names (the value of ldapGroupNameAttribute, not the full DN) whose members should become ICP super-admins on first login:

ldapAdminRoles = ["icp-admins", "administrators"]

The comparison is case-sensitive. A user is placed in the ICP Super Admins group the first time they log in with a matching role. Subsequent role changes in LDAP are not reflected automatically.

TLS (LDAPS)​

For production deployments, enable TLS:

ldapSslEnabled = true

# Path to a JKS truststore containing the LDAP server's CA certificate.
# Required when ldapSslEnabled is true.
ldapTrustStorePath = "../conf/security/ldap-truststore.jks"
ldapTrustStorePassword = "truststore-password"

To import a CA certificate into the truststore:

keytool -importcert -alias ldap-ca \
-file /path/to/ldap-ca.crt \
-keystore ../conf/security/ldap-truststore.jks \
-storepass truststore-password

Directory-specific examples​

OpenLDAP (inetOrgPerson + groupOfNames)​

ldapUserStoreEnabled   = true

ldapHostName = "ldap.example.com"
ldapPort = 389
ldapConnectionName = "cn=admin,dc=example,dc=com"
ldapConnectionPassword = "admin-password"

ldapUserSearchBase = "ou=people,dc=example,dc=com"
ldapUserNameAttribute = "uid"
ldapUserSearchFilter = "(&(objectClass=inetOrgPerson)(uid=?))"
ldapDisplayNameAttribute = "cn"

ldapGroupSearchBase = "ou=groups,dc=example,dc=com"
ldapGroupNameAttribute = "cn"
ldapGroupSearchFilter = "(objectClass=groupOfNames)"
ldapMembershipAttribute = "member"

ldapAdminRoles = ["icp-admins"]

OpenLDAP (posixAccount + posixGroup)​

ldapUserSearchBase       = "ou=people,dc=example,dc=com"
ldapUserNameAttribute = "uid"
ldapUserSearchFilter = "(&(objectClass=posixAccount)(uid=?))"
ldapDisplayNameAttribute = "cn"

ldapGroupSearchBase = "ou=groups,dc=example,dc=com"
ldapGroupNameAttribute = "cn"
ldapGroupSearchFilter = "(objectClass=posixGroup)"
ldapMembershipAttribute = "memberUid"

ldapAdminRoles = ["icp-admins"]

Active Directory​

ldapHostName           = "dc01.corp.example.com"
ldapPort = 389
ldapConnectionName = "CN=svc-icp,OU=Service Accounts,DC=corp,DC=example,DC=com"
ldapConnectionPassword = "service-account-password"

ldapUserSearchBase = "OU=Users,DC=corp,DC=example,DC=com"
ldapUserNameAttribute = "sAMAccountName"
ldapUserSearchFilter = "(&(objectClass=user)(sAMAccountName=?))"
ldapDisplayNameAttribute = "displayName"

# AD populates memberOf on the user entry — no separate group search needed
ldapMemberOfAttribute = "memberOf"
ldapGroupNameAttribute = "cn"

ldapAdminRoles = ["ICP Admins"]

For AD over LDAPS (port 636):

ldapPort               = 636
ldapSslEnabled = true
ldapTrustStorePath = "../conf/security/ad-truststore.jks"
ldapTrustStorePassword = "truststore-password"

How it works​

On login the adapter:

  1. Resolves the user's LDAP Distinguished Name (DN) — either directly from a pattern or via a directory search.
  2. Authenticates the user by attempting an LDAP bind with their DN and password.
  3. Reads the user's group memberships from the directory.
  4. If any group matches a configured admin role, the user is granted ICP super-admin (by adding them to the built-in Super Admins group). This happens only on the user's first login and is not re-evaluated on subsequent logins.
  5. Returns a stable, deterministic user ID (UUID v5 derived from the username and search base) so the same LDAP user always maps to the same ICP user record.

Troubleshooting​

SymptomCauseFix
Login returns 401 and the log shows LDAP user search failed with Entry is not found for DNUser not found in directory. The message names the search base DN even when that DN existsCheck ldapUserSearchBase and ldapUserSearchFilter; verify the username attribute matches the login name
Login returns 500 "Authentication service error" and the log shows Unexpected LDAP error during bindCannot reach LDAP serverCheck ldapHostName, ldapPort, firewall rules
Users can log in but are never super-adminGroup names don't matchldapAdminRoles values must match the ldapGroupNameAttribute value exactly (case-sensitive)
With LDAPS enabled, login returns 401 "Invalid credentials" for valid usersLDAP server certificate not trusted by the truststoreImport the LDAP server's CA cert into the truststore
Users get super-admin on first login but lose it after re-deployExpected behaviourSuper-admin is set once at first login; subsequent changes must be managed via the ICP user management UI
Display name shows as usernameldapDisplayNameAttribute missing on entryVerify the attribute name or set ldapDisplayNameAttribute = "" to always use the username