spring-projects/spring-security · error · InternalAuthenticationServiceException
Bad credentials
Error message
Bad credentials
What it means
ActiveDirectoryLdapAuthenticationProvider.doAuthentication() failed to search for the user after binding, because a NamingException occurred; it logs 'Failed to locate directory entry' and converts the failure to a generic BadCredentialsException with 'Bad credentials' as the message.
Source
Thrown at ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java:183
public ActiveDirectoryLdapAuthenticationProvider(String domain, String url) {
Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty");
this.domain = StringUtils.hasText(domain) ? domain.toLowerCase(Locale.ROOT) : null;
this.url = url;
this.rootDn = (this.domain != null) ? rootDnFromDomain(this.domain) : null;
}
@Override
protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth) {
String username = auth.getName();
String password = (String) auth.getCredentials();
Assert.notNull(password, "password cannot be null");
DirContext ctx = null;
try {
ctx = bindAsUser(username, password);
return searchForUser(ctx, username);
}
catch (CommunicationException ex) {
throw badLdapConnection(ex);
}
catch (NamingException ex) {
this.logger.error("Failed to locate directory entry for authenticated user: " + username, ex);
throw badCredentials(ex);
}
finally {
LdapUtils.closeContext(ctx);
}
}
/**
* Creates the user authority list from the values of the {@code memberOf} attribute
* obtained from the user's Active Directory entry.
*/
@Override
protected Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username,
String password) {
return this.authoritiesPopulator.getGrantedAuthorities(userData, username);View on GitHub (pinned to 96852e8860)
Solutions
- Log/inspect the cause (ex.getCause() is the NamingException) and fix the searchBase or searchFilter so the user DN is resolvable
- Enable debug logging for org.springframework.security.ldap to see the failing search
- Verify the user exists under the configured base and the domain matches the configured rootDn
Example fix
// before
.ad().domain("corp.example.com").userSearchFilter("(cn={1})") // cn used, users keyed by sAMAccountName
// after
.ad().domain("corp.example.com").userSearchFilter("(sAMAccountName={0})") Defensive patterns
Strategy: try-catch
Try / catch
try {
authenticationManager.authenticate(adToken);
} catch (BadCredentialsException e) {
Throwable cause = e.getCause(); // NamingException from searchForUser
logger.error("AD lookup failed; check searchBase/searchFilter", cause);
} Prevention
- Validate searchBase/searchFilter against the real directory (ldapsearch) before deploying
- Enable DEBUG logging for org.springframework.security.ldap
- Keep the cause chain intact so the underlying NamingException is inspectable
- Test with users from every OU covered by the search base
When it happens
Trigger: bindAsUser succeeded but searchForUser threw NamingException (e.g. user DN not found under configured searchBase, search filter mismatch, directory referral issues) — the underlying cause is the wrapped NamingException.
Common situations: Wrong searchFilter/searchBase configuration so the authenticated user's DN is not found; user exists in a different AD domain than the search base; transient directory errors surfaced as credentials error.
Related errors
- Bad credentials
- Bad credentials
- Bad credentials
- <namingException.getMessage()>
- Connection to LDAP server failed.
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/0d664f67c60ff1a7.
Report an issue: GitHub.