Skip to main content

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.

Activate the adapter

ldapUserStoreEnabled = true

Server connection

ldapHostName = "ldap.example.com"   # default: localhost
ldapPort = 10389 # default: 10389; 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 — construct the DN directly without a search (see below)
ldapDisplayNameAttribute(empty)Attribute used as the display name in ICP; leave 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).

Group / role lookup

ICP reads groups to determine whether a user should be granted super-admin. 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).

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.
# If omitted, certificate verification is disabled (not recommended for production).
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 on first login (by adding them to the built-in Super Admins group).
  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 with no error in logsUser not found in directoryCheck ldapUserSearchBase and ldapUserSearchFilter; verify the username attribute matches the login name
Login returns 500 "Authentication service unavailable"Cannot 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)
TLS handshake failureCA certificate not trustedImport 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