spring-projects/spring-security · error · UncategorizedLdapException

<namingException.getMessage()>

Error message

<namingException.getMessage()>

What it means

PasswordPolicyAwareContextSource.getContext catches NamingExceptions raised while obtaining an LDAP context. If a password policy response control indicates the account is locked with an error status, it throws PasswordPolicyException with that status; otherwise it converts the NamingException via LdapUtils.convertLdapException(ex), surfacing the raw naming exception message. This distinguishes password-policy failures (locked account, expired password) from generic directory errors.

Source

Thrown at ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java:71

		this.logger.trace(LogMessage.format("Binding as %s, prior to reconnect as user %s", getUserDn(), principal));
		// First bind as manager user before rebinding as the specific principal.
		LdapContext ctx = (LdapContext) super.getContext(getUserDn(), getPassword());
		Control[] rctls = { new PasswordPolicyControl(false) };
		try {
			ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, principal);
			ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);
			ctx.reconnect(rctls);
		}
		catch (javax.naming.NamingException ex) {
			PasswordPolicyResponseControl ctrl = PasswordPolicyControlExtractor.extractControl(ctx);
			if (this.logger.isDebugEnabled()) {
				this.logger.debug(LogMessage.format("Failed to bind with %s", ctrl), ex);
			}
			LdapUtils.closeContext(ctx);
			if (ctrl != null && ctrl.isLocked() && ctrl.getErrorStatus() != null) {
				throw new PasswordPolicyException(ctrl.getErrorStatus());
			}
			throw LdapUtils.convertLdapException(ex);
		}
		this.logger.debug(LogMessage.of(() -> "Bound with " + PasswordPolicyControlExtractor.extractControl(ctx)));
		return ctx;
	}

	@Override
	@SuppressWarnings("unchecked")
	protected Hashtable getAuthenticatedEnv(String principal, String credentials) {
		Hashtable<String, Object> env = super.getAuthenticatedEnv(principal, credentials);
		env.put(LdapContext.CONTROL_FACTORIES, PasswordPolicyControlFactory.class.getName());
		return env;
	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. If PasswordPolicyException reports a lock, unlock the account in the directory or wait out the lockout policy.
  2. Check the converted exception message for expired-password or invalid-credentials hints and have the user reset/change the password.
  3. Verify bind credentials and the directory's password policy configuration (ppolicy overlay in OpenLDAP, fine-grained policy in 389DS).
  4. Confirm network connectivity to the LDAP server if the message indicates a communication problem.

Example fix

// before: application keeps retrying binds for a locked account
Authentication result = provider.authenticate(token);
// after: catch policy errors and surface account state
try {
  result = provider.authenticate(token);
} catch (PasswordPolicyException ex) {
  throw new LockedException("Account locked: " + ex.getMessage());
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    Authentication a = provider.authenticate(token);
} catch (PasswordPolicyException e) {
    // map to LockedException/CredentialsExpiredException for user-friendly UI
} catch (org.springframework.security.authentication.BadCredentialsException e) {
    // wrong username/password
}

Prevention

When it happens

Trigger: Calling getContext (used during authentication binds) when the LDAP bind fails: account locked per password policy control (PasswordPolicyException with error status) or any underlying JNDI error (bad credentials, communication failure).

Common situations: User exceeded failed-login attempts and the directory locked the account; password expired and mustChangePassword is set; directory unreachable; wrong bind DN/password for the manager or user account.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/55fbd1c315ff7508. Report an issue: GitHub.