apereo/cas · error · FailedLoginException
Invalid credentials
Error message
Invalid credentials
What it means
LdapAuthenticationHandler asks the configured password policy handling strategy whether it can interpret the ldaptive AuthenticationResponse. If strategy.supports(response) is false, the handler gives up and throws FailedLoginException 'Invalid credentials', even though the bind may otherwise have succeeded.
Solutions
- Switch passwordPolicyHandlingStrategy to DEFAULT (or the strategy matching your directory, e.g. AD-specific one for Active Directory).
- Confirm the ldap authType (AD/DIRECT/BIND/SEARCH) matches the actual directory server.
- Check the warning log line naming the unsupported strategy and response to see the mismatch.
- Upgrade/align the ldaptive library version so the response type is recognized.
Example fix
// before cas.authn.ldap[0].password-policy-strategy= GrooviePasswordPolicyHandlingStrategy // after cas.authn.ldap[0].password-policy-strategy=DEFAULT
Defensive patterns
Strategy: try-catch
Try / catch
try { result = handler.authenticate(credential); }
catch (FailedLoginException e) {
if ("Invalid credentials".equals(e.getMessage())) { checkLdapPolicyStrategyConfig(); }
} Prevention
- Use the DEFAULT password policy strategy unless you know the directory type.
- Keep ldap authType consistent with the server (AD vs generic).
- Watch for the 'cannot handle' WARN line when first configuring LDAP.
When it happens
Trigger: cas.authn.ldap[].passwordPolicyHandlingStrategy is set to a strategy (e.g. GROOWIE, EXTENDED) whose response type does not match the response produced by the configured authenticator/type (AD vs generic LDAP).
Common situations: Configuring AD-specific password policy strategy against a non-Active Directory directory; custom authenticator returning responses the strategy cannot parse; copy-pasted LDAP config between server types.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authentication has failed because LDAP password policy…
- Unable to authenticate
- Multiple principal values are not allowed: [principalAttr]
- Could not update the LDAP entry's password for [filter] and…
- Could not authenticate provided credentials
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/c596574f99cdffd8.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java:124
}
if (this.principalAttributeMap != null && !this.principalAttributeMap.isEmpty()) {
val attrs = this.principalAttributeMap.keySet();
attributes.addAll(attrs);
LOGGER.debug("Configured to retrieve principal attribute collection of [{}]", attrs);
}
this.authenticatedEntryAttributes = attributes.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
LOGGER.debug("LDAP authentication entry attributes for the authentication request are [{}]", (Object[]) this.authenticatedEntryAttributes);
}
@Override
protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential upc,
@Nullable final String originalPassword) throws Throwable {
val response = getLdapAuthenticationResponse(upc);
LOGGER.debug("LDAP response: [{}]", response);
if (!passwordPolicyHandlingStrategy.supports(response)) {
LOGGER.warn("Authentication has failed because LDAP password policy handling strategy [{}] cannot handle [{}].",
response, passwordPolicyHandlingStrategy.getClass().getSimpleName());
throw new FailedLoginException("Invalid credentials");
}
LOGGER.debug("Attempting to examine and handle LDAP password policy via [{}]",
passwordPolicyHandlingStrategy.getClass().getSimpleName());
val messageList = passwordPolicyHandlingStrategy.handle(response, getPasswordPolicyConfiguration());
if (response.isSuccess()) {
LOGGER.debug("LDAP response returned a result [{}], creating the final LDAP principal", response.getLdapEntry());
val principal = createPrincipal(upc.getUsername(), response.getLdapEntry());
return createHandlerResult(upc, principal, messageList);
}
if (AuthenticationResultCode.DN_RESOLUTION_FAILURE == response.getAuthenticationResultCode()) {
LOGGER.warn("DN resolution failed. [{}]", response.getDiagnosticMessage());
throw new AccountNotFoundException(upc.getUsername() + " not found.");
}
throw new FailedLoginException("Invalid credentials");
}
/**
* Creates a CAS principal with attributes if the LDAP entry contains principal attributes.View on GitHub (pinned to e7288fc434)