{"record":{"id":"55fbd1c315ff7508","repo":"spring-projects/spring-security","slug":"namingexception-getmessage-55fbd1","errorCode":null,"errorMessage":"<namingException.getMessage()>","messagePattern":"<namingException\\.getMessage\\(\\)>","errorType":"exception","errorClass":"UncategorizedLdapException","httpStatus":null,"severity":"error","filePath":"ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java","lineNumber":71,"sourceCode":"\t\tthis.logger.trace(LogMessage.format(\"Binding as %s, prior to reconnect as user %s\", getUserDn(), principal));\n\t\t// First bind as manager user before rebinding as the specific principal.\n\t\tLdapContext ctx = (LdapContext) super.getContext(getUserDn(), getPassword());\n\t\tControl[] rctls = { new PasswordPolicyControl(false) };\n\t\ttry {\n\t\t\tctx.addToEnvironment(Context.SECURITY_PRINCIPAL, principal);\n\t\t\tctx.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);\n\t\t\tctx.reconnect(rctls);\n\t\t}\n\t\tcatch (javax.naming.NamingException ex) {\n\t\t\tPasswordPolicyResponseControl ctrl = PasswordPolicyControlExtractor.extractControl(ctx);\n\t\t\tif (this.logger.isDebugEnabled()) {\n\t\t\t\tthis.logger.debug(LogMessage.format(\"Failed to bind with %s\", ctrl), ex);\n\t\t\t}\n\t\t\tLdapUtils.closeContext(ctx);\n\t\t\tif (ctrl != null && ctrl.isLocked() && ctrl.getErrorStatus() != null) {\n\t\t\t\tthrow new PasswordPolicyException(ctrl.getErrorStatus());\n\t\t\t}\n\t\t\tthrow LdapUtils.convertLdapException(ex);\n\t\t}\n\t\tthis.logger.debug(LogMessage.of(() -> \"Bound with \" + PasswordPolicyControlExtractor.extractControl(ctx)));\n\t\treturn ctx;\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tprotected Hashtable getAuthenticatedEnv(String principal, String credentials) {\n\t\tHashtable<String, Object> env = super.getAuthenticatedEnv(principal, credentials);\n\t\tenv.put(LdapContext.CONTROL_FACTORIES, PasswordPolicyControlFactory.class.getName());\n\t\treturn env;\n\t}\n\n}\n","sourceCodeStart":53,"sourceCodeEnd":86,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java#L53-L86","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["If PasswordPolicyException reports a lock, unlock the account in the directory or wait out the lockout policy.","Check the converted exception message for expired-password or invalid-credentials hints and have the user reset/change the password.","Verify bind credentials and the directory's password policy configuration (ppolicy overlay in OpenLDAP, fine-grained policy in 389DS).","Confirm network connectivity to the LDAP server if the message indicates a communication problem."],"exampleFix":"// before: application keeps retrying binds for a locked account\nAuthentication result = provider.authenticate(token);\n// after: catch policy errors and surface account state\ntry {\n  result = provider.authenticate(token);\n} catch (PasswordPolicyException ex) {\n  throw new LockedException(\"Account locked: \" + ex.getMessage());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    Authentication a = provider.authenticate(token);\n} catch (PasswordPolicyException e) {\n    // map to LockedException/CredentialsExpiredException for user-friendly UI\n} catch (org.springframework.security.authentication.BadCredentialsException e) {\n    // wrong username/password\n}","preventionTips":["Configure password policy handling (ppolicy) and map its error statuses to UX flows.","Expose account-lock/expired states distinctly instead of generic login failure.","Monitor lockout rates to catch credential-stuffing attacks.","Set sensible lockout durations so legitimate users are not stranded."],"tags":["ldap","password-policy","account-locked","authentication"],"backgroundTag":"permission-denied","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}