apereo/cas · error · BadCredentialsException

Could not authenticate provided credentials

Error message

Could not authenticate provided credentials

What it means

When the LDAP authentication completes without a thrown exception but yields no successful result — no response results, or none containing a resolved entry/authenticated user — the provider throws BadCredentialsException("Could not authenticate provided credentials") as its final statement.

Solutions

  1. Verify the username exists in LDAP and matches the user filter under the configured base DN
  2. Double-check the supplied password
  3. Run ldapsearch with the same base DN and filter to confirm the entry is visible to the bind account
  4. Confirm the user is not disabled/locked (directories often return no-result style failures)
  5. Adjust base-dn/user-filter if the entry lives elsewhere

Example fix

// before
// user-filter=(uid={user}) but directory keys on sAMAccountName
// after
// user-filter=(sAMAccountName={user})
Defensive patterns

Strategy: validation

Validate before calling

// confirm the user exists before attempting endpoint auth
SearchResult entry = LdapUtils.getLdapEntry(props, "(sAMAccountName=" + user + ")");
boolean userExists = entry != null;

Try / catch

try {
    provider.authenticate(token);
} catch (BadCredentialsException e) {
    // treat as invalid username/password — do NOT retry, return 401
}

Prevention

When it happens

Trigger: authenticate() runs to completion, no Throwable is thrown, but authenticator.authenticate(request) returns a response with zero results (user does not exist, filter does not match) or an unauthenticated result.

Common situations: Typo in username/password for a real user; user does not exist under the configured base DN; user-filter does not match the entry; account exists but bind DN cannot read it; password simply wrong.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/5caa54feefca0089. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authorization/EndpointLdapAuthenticationProvider.java:112

                entry.getAttributes().forEach(attribute -> attributes.put(attribute.getName(), new ArrayList<>(attribute.getStringValues())));
                val principal = PrincipalFactoryUtils.newPrincipalFactory().createPrincipal(username, attributes);
                val authZGen = buildAuthorizationGenerator();
                val authorities = authZGen.apply(Objects.requireNonNull(principal));

                LOGGER.debug("List of authorities remapped from profile roles are [{}]", authorities);
                if (authorities.stream().anyMatch(authority -> requiredRoles.contains(authority.getAuthority()))) {
                    return generateAuthenticationToken(authentication, authorities);
                }
                LOGGER.warn("User [{}] is not authorized to access the requested resource", username);
            } else {
                LOGGER.warn("LDAP authentication response produced no results for [{}]", username);
            }

        } catch (final Throwable e) {
            LoggingUtils.error(LOGGER, e);
            throw new InsufficientAuthenticationException("Unexpected LDAP error", e);
        }
        throw new BadCredentialsException("Could not authenticate provided credentials");
    }

    @Override
    public boolean supports(final Class<?> aClass) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    }

    private Function<Principal, List<SimpleGrantedAuthority>> buildAuthorizationGenerator() {
        val properties = ldapProperties.getLdapAuthz();

        if (isGroupBasedAuthorization()) {
            LOGGER.debug("Handling LDAP authorization based on groups");
            return new LdapUserGroupsToRolesAuthorizationGenerator(
                ldapAuthorizationGeneratorUserSearchOperation(),
                properties.isAllowMultipleResults(),
                properties.getGroupAttribute(),
                properties.getGroupPrefix(),
                ldapAuthorizationGeneratorGroupSearchOperation());

View on GitHub (pinned to e7288fc434)