I have a Keycloak instance that is talking to an AD on Server 2016 via LDAPS. I have verified that the connection to the server is working, that the connection is encrypted, and that the Bind user in keycloak can authenticate.
AND YET, when attempting to change a password, I get the following error:
The keycloak bind user has FULL write access over the whole domain, so I really do not see any reason for AD to reject external write access.
Connecting to the server via ldapsearch with ldapsearch -x -H ldaps://<DC FQDN>:636 -D "cn=Keycloak-Sync2,ou=SpecialUsers,ou=<company>,dc=<company domain>,dc=de" -b "ou=Team,ou=<Company>,dc=<company domain>,dc=de" -w "<password>"
The BindDN (-D option) is exactly equal to the Bind DN in keycloak, and the Base DN (-b option) is exactly equal to the users DN in keycloak, and I get a list of all the users as a result.
I also get the following error in the Keycloak log:
8:26:53,153 INFO [org.keycloak.storage.ldap.LDAPIdentityStoreRegistry] (Timer-2) Creating new LDAP Store for the LDAP storage provider: 'ldap', LDAP Configuration: {fullSyncPeriod=[86400], pagination=[true], connectionPooling=[false], usersDn=[ou=Team,ou=<company name>,dc=<company domain>,dc=de], cachePolicy=[DEFAULT], useKerberosForPasswordAuthentication=[false], importEnabled=[true], enabled=[true], bindDn=[CN=Keycloak-Sync2,ou=SpecialUsers,ou=<company name>,dc=<company domain>,dc=de], usernameLDAPAttribute=[sAMAccountName], changedSyncPeriod=[900], lastSync=[1734287212], vendor=[ad], uuidLDAPAttribute=[objectGUID], connectionUrl=[ldaps://dc02.<company domain>.de:636], allowKerberosAuthentication=[false], syncRegistrations=[false], authType=[simple], debug=[false], searchScope=[2], useTruststoreSpi=[ldapsOnly], usePasswordModifyExtendedOp=[true], trustEmail=[true], priority=[0], userObjectClasses=[person, organizationalPerson, user], rdnLDAPAttribute=[sAMAccountName], editMode=[WRITABLE], validatePasswordPolicy=[false], batchSizeForSync=[1000]}, binaryAttributes: []
18:26:53,200 INFO [org.keycloak.truststore.SSLSocketFactory] (Timer-2) No truststore provider found - using default SSLSocketFactory
18:26:54,022 INFO [org.keycloak.storage.ldap.LDAPStorageProviderFactory] (Timer-2) Sync of federation mapper 'role-mapper' finished. Status: UserFederationSyncResult [ 0 imported roles, 67 roles already exists in Keycloak ]
18:26:54,027 INFO [org.keycloak.storage.ldap.LDAPStorageProviderFactory] (Timer-2) Sync changed users from LDAP to local store: realm: <COMPANY DOMAIN>.DE, federation provider: ldap, last sync time: Sun Dec 15 18:07:41 GMT 2024
18:26:54,218 INFO [org.keycloak.storage.ldap.LDAPStorageProviderFactory] (Timer-2) Sync changed users finished: 0 imported users, 0 updated users
18:36:58,665 WARN [org.keycloak.events] (default task-2) type=LOGIN_ERROR, realmId=master, clientId=null, userId=null, ipAddress=10.42.0.2, error=expired_code, restart_after_timeout=true, authSessionParentId=89cdcdbd-5f32-47a2-9c69-1d83f8eca814, authSessionTabId=g8xANkYl1M0
18:37:04,130 WARN [org.keycloak.events] (default task-1) type=LOGIN_ERROR, realmId=master, clientId=security-admin-console, userId=null, ipAddress=10.42.0.2, error=user_not_found, auth_method=openid-connect, redirect_uri=https://auth.<company domain>.de/auth/admin/master/console/, code_id=89cdcdbd-5f32-47a2-9c69-1d83f8eca814, username=<windows username>, authSessionParentId=89cdcdbd-5f32-47a2-9c69-1d83f8eca814, authSessionTabId=g8xANkYl1M0
18:38:30,022 WARN [org.keycloak.services.resources.admin.UserResource] (default task-3) Could not update user password.: org.keycloak.models.ModelException: Could not modify attribute for DN [CN=<name of user>,OU=Team,OU=<company name>,DC=<company domain>,DC=de]
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.modifyAttributes(LDAPOperationManager.java:609)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore.updateADPassword(LDAPIdentityStore.java:399)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore.updatePassword(LDAPIdentityStore.java:367)
at [email protected]//org.keycloak.storage.ldap.LDAPStorageProvider.updateCredential(LDAPStorageProvider.java:666)
at [email protected]//org.keycloak.credential.UserCredentialStoreManager.updateCredential(UserCredentialStoreManager.java:184)
at [email protected]//org.keycloak.services.resources.admin.UserResource.resetPassword(UserResource.java:614)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at [email protected]//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at [email protected]//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at [email protected]//org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at [email protected]//org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:60)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
at [email protected]//javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at [email protected]//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at [email protected]//org.keycloak.provider.wildfly.WildFlyRequestFilter.lambda$doFilter$0(WildFlyRequestFilter.java:41)
at [email protected]//org.keycloak.services.filters.AbstractRequestFilter.filter(AbstractRequestFilter.java:43)
at [email protected]//org.keycloak.provider.wildfly.WildFlyRequestFilter.doFilter(WildFlyRequestFilter.java:39)
at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at [email protected]//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.lambda$handleRequest$1(ElytronRunAsHandler.java:68)
at [email protected]//org.wildfly.security.auth.server.FlexibleIdentityAssociation.runAsFunctionEx(FlexibleIdentityAssociation.java:103)
at [email protected]//org.wildfly.security.auth.server.Scoped.runAsFunctionEx(Scoped.java:161)
at [email protected]//org.wildfly.security.auth.server.Scoped.runAs(Scoped.java:73)
at [email protected]//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.handleRequest(ElytronRunAsHandler.java:67)
at [email protected]//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at org.wildfly.security.elytron-web.undertow-server-servlet@1.10.1.Final//org.wildfly.elytron.web.undertow.server.servlet.CleanUpHandler.handleRequest(CleanUpHandler.java:38)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at [email protected]//io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:275)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1544)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1544)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1544)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1544)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:255)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100)
at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at [email protected]//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: javax.naming.NoPermissionException: [LDAP: error code 50 - 00000005: SecErr: DSID-031A11EF, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
]; remaining name 'CN=<name of user>,OU=Team,OU=<company name>,DC=<company domain>,DC=de'
at java.naming/com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3267)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3205)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2996)
at java.naming/com.sun.jndi.ldap.LdapCtx.c_modifyAttributes(LdapCtx.java:1504)
at java.naming/com.sun.jndi.toolkit.ctx.ComponentDirContext.p_modifyAttributes(ComponentDirContext.java:277)
at java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.modifyAttributes(PartialCompositeDirContext.java:192)
at java.naming/javax.naming.directory.InitialDirContext.modifyAttributes(InitialDirContext.java:172)
at java.naming/javax.naming.directory.InitialDirContext.modifyAttributes(InitialDirContext.java:172)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager$6.execute(LDAPOperationManager.java:590)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager$6.execute(LDAPOperationManager.java:586)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:731)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:711)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.modifyAttributesNaming(LDAPOperationManager.java:586)
at [email protected]//org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.modifyAttributes(LDAPOperationManager.java:607)
... 87 more
What could the reason be that AD does not let Keycloak change the user password?
(INSUFF_ACCESS_RIGHTS)
what account are you attempting to change the password for? Is it a protected account or a regular user account?