spring-projects/spring-security · error · UncategorizedLdapException
<namingException.getMessage()>
Error message
<namingException.getMessage()>
What it means
ActiveDirectoryLdapAuthenticationProvider's bindAsUser binds as the authenticating user against Active Directory. If the resulting NamingException is an AuthenticationException or OperationNotSupportedException it is treated as bad credentials; any other NamingException is converted with LdapUtils.convertLdapException(ex) and thrown with the original naming exception's message. This propagates infrastructure-level LDAP failures rather than masking them as login failures.
Source
Thrown at ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java:223
// TODO. add DNS lookup based on domain
Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String bindPrincipal = createBindPrincipal(username);
env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
env.put(Context.PROVIDER_URL, this.url);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.OBJECT_FACTORIES, DefaultDirObjectFactory.class.getName());
env.putAll(this.contextEnvironmentProperties);
try {
return this.contextFactory.createContext(env);
}
catch (NamingException ex) {
if ((ex instanceof AuthenticationException) || (ex instanceof OperationNotSupportedException)) {
handleBindException(bindPrincipal, ex);
throw badCredentials(ex);
}
throw LdapUtils.convertLdapException(ex);
}
}
private void handleBindException(String bindPrincipal, NamingException exception) {
this.logger.debug(LogMessage.format("Authentication for %s failed:%s", bindPrincipal, exception));
handleResolveObj(exception);
int subErrorCode = parseSubErrorCode(exception.getMessage());
if (subErrorCode <= 0) {
this.logger.debug("Failed to locate AD-specific sub-error code in message");
return;
}
this.logger
.info(LogMessage.of(() -> "Active Directory authentication failed: " + subCodeToLogMessage(subErrorCode)));
if (this.convertSubErrorCodesToExceptions) {
raiseExceptionForErrorCode(subErrorCode, exception);
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Verify the AD domain and URL configured in ActiveDirectoryLdapAuthenticationProvider (domain + rootDn/url) resolve and are reachable from the app.
- Check the cause chain of the converted exception for the underlying JNDI diagnostic.
- If using LDAPS, confirm the DC certificate is trusted by the JVM truststore to avoid SSL handshake NamingExceptions.
- Confirm port correctness: 389/636 (or 3268/3269 for GC) and no firewall blocking.
Example fix
// before: wrong URL scheme causing connect NamingException
new ActiveDirectoryLdapAuthenticationProvider("example.com", "ldaps://dc.example.com:389");
// after: port matches scheme
new ActiveDirectoryLdapAuthenticationProvider("example.com", "ldaps://dc.example.com:636"); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight AD connectivity and cert trust
SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
try (Socket s = f.createSocket(dcHost, 636)) {
assert s.isConnected();
} catch (IOException e) {
fail("AD endpoint unreachable: " + e.getMessage());
} Try / catch
try {
provider.authenticate(token);
} catch (org.springframework.security.authentication.InternalAuthenticationServiceException e) {
Throwable root = ExceptionUtils.getRootCause(e);
log.error("AD bind infrastructure failure", root); // distinguish from BadCredentialsException
} Prevention
- Smoke-test DC host:port reachability from the deployment environment.
- Import LDAPS certificates into the JVM truststore before rollout.
- Pin registration of the provider behind a health-check that binds as a service account.
- Log the JNDI exception's message/cause separately from bad-credential paths.
When it happens
Trigger: Calling authenticate() (via doAuthentication -> bindAsUser) when the AD bind throws a non-authentication NamingException: server unreachable, port 636/389 wrong, DNS resolution failure, or AD refusing the operation for reasons other than bad password.
Common situations: AD domain controller hostname typo or unreachable DC, using wrong port (LDAPS vs LDAP), connectivity/firewall issues in DMZ, or AD returning unexpected errors like unavailable server or time skew (KRB5/NTLM mismatches).
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Connection to LDAP server failed.
- <namingException.getMessage()>
- Bad credentials
- Failed to obtain DirContext
- Empty Username
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/5f973abbc4d803d0.
Report an issue: GitHub.