{"record":{"id":"646c91bb014825cc","repo":"apereo/cas","slug":"authentication-has-failed-because-ldap-password-po","errorCode":null,"errorMessage":"Authentication has failed because LDAP password policy handling strategy [{}] cannot handle [{}].","messagePattern":"Authentication has failed because LDAP password policy handling strategy \\[(.+?)\\] cannot handle \\[(.+?)\\]\\.","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java","lineNumber":122,"sourceCode":"            LOGGER.debug(\"Configured to retrieve principal id attribute [{}]\", this.principalIdAttribute);\n            attributes.add(this.principalIdAttribute);\n        }\n        if (this.principalAttributeMap != null && !this.principalAttributeMap.isEmpty()) {\n            val attrs = this.principalAttributeMap.keySet();\n            attributes.addAll(attrs);\n            LOGGER.debug(\"Configured to retrieve principal attribute collection of [{}]\", attrs);\n        }\n        this.authenticatedEntryAttributes = attributes.toArray(ArrayUtils.EMPTY_STRING_ARRAY);\n        LOGGER.debug(\"LDAP authentication entry attributes for the authentication request are [{}]\", (Object[]) this.authenticatedEntryAttributes);\n    }\n\n    @Override\n    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential upc,\n                                                                                        @Nullable final String originalPassword) throws Throwable {\n        val response = getLdapAuthenticationResponse(upc);\n        LOGGER.debug(\"LDAP response: [{}]\", response);\n        if (!passwordPolicyHandlingStrategy.supports(response)) {\n            LOGGER.warn(\"Authentication has failed because LDAP password policy handling strategy [{}] cannot handle [{}].\",\n                response, passwordPolicyHandlingStrategy.getClass().getSimpleName());\n            throw new FailedLoginException(\"Invalid credentials\");\n        }\n        LOGGER.debug(\"Attempting to examine and handle LDAP password policy via [{}]\",\n            passwordPolicyHandlingStrategy.getClass().getSimpleName());\n        val messageList = passwordPolicyHandlingStrategy.handle(response, getPasswordPolicyConfiguration());\n        if (response.isSuccess()) {\n            LOGGER.debug(\"LDAP response returned a result [{}], creating the final LDAP principal\", response.getLdapEntry());\n            val principal = createPrincipal(upc.getUsername(), response.getLdapEntry());\n            return createHandlerResult(upc, principal, messageList);\n        }\n        if (AuthenticationResultCode.DN_RESOLUTION_FAILURE == response.getAuthenticationResultCode()) {\n            LOGGER.warn(\"DN resolution failed. [{}]\", response.getDiagnosticMessage());\n            throw new AccountNotFoundException(upc.getUsername() + \" not found.\");\n        }\n        throw new FailedLoginException(\"Invalid credentials\");\n    }\n","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java#L104-L140","documentation":"This error is thrown by CAS's LDAP authentication handler when the configured password policy handling strategy does not support the LdapAuthenticationResponse returned by the directory. The strategy (e.g. GNUPasswordPolicy, ActiveDirectory) can only interpret specific response/controls; when it cannot handle the response, CAS treats the attempt as a failed login and throws FailedLoginException. It usually signals a mismatch between the directory type and the configured passwordPolicyHandlingStrategy.","triggerScenarios":"A login attempt reaches LdapAuthenticationHandler.authenticateUsernamePasswordInternal, getLdapAuthenticationResponse returns a response, and passwordPolicyHandlingStrategy.supports(response) returns false — e.g. strategy set to a specific policy type while the bind result carries no policy request/response controls, or using the GNU/AD strategy against a directory that returns none of the expected controls.","commonSituations":"Setting cas.authn.ldap[0].password-policy.type to an ActiveDirectory-specific strategy while authenticating against OpenLDAP (or vice versa); customizing the strategy class whose supports() rejects null/empty responses; LDAP server upgraded and stopped returning password-policy controls; strategy misconfigured for the authentication method (anonymous bind vs password comparison).","solutions":["Set the password policy type (cas.authn.ldap[0].password-policy.type) to a strategy matching your directory (AD, FreeIPA, GNU, or default/custom)","Enable the password policy request control on the LDAP connection (enablePasswordPolicyControls / connection pool controls) so the response carries data the strategy supports","Inspect the logged 'LDAP response: [{}]' debug line to see what the response actually contains and adjust the strategy accordingly","If policy handling is not needed, use the default strategy that accepts any response","Update any custom PasswordPolicyHandlingStrategy so supports() matches the response types your server returns"],"exampleFix":"// before\ncas.authn.ldap[0].password-policy.type=ActiveDirectory\n// against OpenLDAP\n// after\ncas.authn.ldap[0].password-policy.type=GNU\ncas.authn.ldap[0].password-policy.warning-attribute-display=false","handlingStrategy":"validation","validationCode":"// Pre-check strategy/response compatibility before login attempts\nif (!ldapPasswordPolicyStrategy.supports(response)) {\n    LOGGER.warn(\"Strategy {} cannot handle response {}; reconfigure cas.authn.ldap[0].password-policy.type\",\n        ldapPasswordPolicyStrategy.getClass().getSimpleName(), response.getAuthenticationResultCode());\n}","typeGuard":"if (response != null && passwordPolicyHandlingStrategy.supports(response)) {\n    // safe to call handle()\n}","tryCatchPattern":"try {\n    return handler.authenticate(credential);\n} catch (FailedLoginException e) {\n    LOGGER.warn(\"LDAP login rejected: {} — verify password-policy strategy matches directory controls\", e.getMessage());\n    return AuthenticationResult.FAILED;\n}","preventionTips":["Match the configured password-policy.type to the actual directory server (AD vs OpenLDAP vs FreeIPA)","Enable the password policy request control on the LDAP connection","Test the strategy with a known-bad password and a known-good password in staging","Log the raw LDAP response at debug level when troubleshooting","Write a unit test asserting supports() returns true for your server's response type"],"tags":["ldap","authentication","password-policy","configuration"],"backgroundTag":"invalid-config-value","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}