Keycloak can sync users from Active Directory, but the most surprising thing is how much control you have over which users get synced and how their attributes are mapped, often leading to unexpected results if not configured precisely.

Let’s see this in action. Imagine we have an Active Directory with users alice.smith and bob.jones.

# In AD, user object looks something like this (simplified):
# DN: CN=Alice Smith,OU=Users,DC=example,DC=com
# sAMAccountName: alice.smith
# givenName: Alice
# sn: Smith
# mail: alice.smith@example.com
# memberOf: CN=Developers,OU=Groups,DC=example,DC=com

# DN: CN=Bob Jones,OU=Users,DC=example,DC=com
# sAMAccountName: bob.jones
# givenName: Bob
# sn: Jones
# mail: bob.jones@example.com
# memberOf: CN=Testers,OU=Groups,DC=example,DC=com

In Keycloak, we configure an LDAP User Federation provider.

Keycloak Admin Console -> User Federation -> Add provider -> LDAP

Here’s a typical configuration snippet:

  • Connection URL: ldap://dc.example.com:389
  • Bind DN: cn=keycloak,ou=Service Accounts,dc=example,dc=com
  • Bind Credentials: your_secret_password
  • User LDAP Filter: (objectClass=user)
  • Username LDAP Attribute: sAMAccountName
  • RDN LDAP Attribute: cn
  • UUID LDAP Attribute: objectGUID
  • User LDAP Filter: (&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))

With this setup, when Keycloak syncs, it will discover alice.smith and bob.jones.

  • alice.smith will appear in Keycloak with username alice.smith, first name Alice, last name Smith, and email alice.smith@example.com.
  • bob.jones will appear in Keycloak with username bob.jones, first name Bob, last name Jones, and email bob.jones@example.com.

This federation allows Keycloak to authenticate users directly against Active Directory without importing their credentials. When a user logs in, Keycloak performs a bind to AD with the provided credentials. If successful, the user is authenticated. The sync process populates Keycloak’s internal user store with user information from AD, enabling features like user listing and role mapping.

The magic happens in the User LDAP Filter. This isn’t just a simple filter; it’s a powerful LDAP query. The example (&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) is crucial. (objectClass=user) ensures only user objects are considered. !(userAccountControl:1.2.840.113556.1.4.803:=2) is an AD-specific filter that excludes disabled user accounts (the userAccountControl attribute with the ACCOUNTDISABLE flag set). Without this, disabled AD users would still be synced and potentially able to log in.

You can get much more granular. Suppose you only want users from a specific Organizational Unit (OU) or members of a particular group. You’d modify the User LDAP Filter. For example, to sync only users in the OU=KeycloakUsers,DC=example,DC=com OU:

  • User LDAP Filter: (&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(memberOf=CN=SyncToKeycloak,OU=Groups,DC=example,DC=com))

This filter now requires users to be part of the SyncToKeycloak group and not be disabled.

Attribute mapping is equally important. Keycloak allows you to define how AD attributes map to Keycloak user attributes. For instance, you might want to map displayName from AD to the username in Keycloak, or map physicalDeliveryOfficeName to a custom Keycloak attribute.

Keycloak Admin Console -> User Federation -> [Your LDAP Provider] -> Mappers tab

Here, you’d add mappers. A common one is mapping mail to email:

  • Name: ad-email-mapper
  • Mapper Type: Attribute Importer
  • LDAP Attribute: mail
  • Keycloak Attribute: email
  • User Attribute: true

This ensures that the mail attribute from AD is imported and set as the email attribute for the user in Keycloak. You can also map AD groups to Keycloak roles using "Group to Role Mapper" types.

The Sync Period setting determines how often Keycloak polls AD for changes. A value of 1h means it checks every hour. During a sync, Keycloak fetches users based on the User LDAP Filter and updates existing users, creates new users, and can even disable or delete users in Keycloak if they are no longer present in AD (controlled by the "On Missing Users" setting).

A critical detail often overlooked is the objectGUID attribute. Keycloak uses this as the definitive identifier for users. When syncing, Keycloak stores the AD objectGUID and uses it to match users across syncs. If this attribute is not correctly mapped or if AD’s objectGUID changes (which it shouldn’t under normal circumstances, but can happen in complex AD migrations), Keycloak might fail to update existing users or create duplicates. Ensure your UUID LDAP Attribute is set to objectGUID.

The "Search Base DN" is another key configuration. This specifies the starting point in your AD tree for searching users. If you set it too high (e.g., DC=example,DC=com), Keycloak will scan your entire domain, which can be slow and resource-intensive. It’s best practice to set it to the lowest common OU that contains all your target users, like OU=Users,DC=example,DC=com.

Finally, remember that if your AD uses LDAPS (LDAP over SSL/TLS), you’ll need to configure the Connection URL to ldaps://dc.example.com:636 and ensure the Keycloak server has the necessary CA certificates installed to trust your AD’s LDAP server certificate.

Once everything is set up, the next challenge will be managing the synchronization of AD groups to Keycloak roles, which involves understanding group membership queries and role mapping configurations.

Want structured learning?

Take the full Keycloak course →