{"record":{"id":"c69eff642024f656","repo":"spring-projects/spring-security","slug":"user-is-disabled-c69eff","errorCode":null,"errorMessage":"User is disabled","messagePattern":"User is disabled","errorType":"exception","errorClass":"DisabledException","httpStatus":null,"severity":"error","filePath":"ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java","lineNumber":267,"sourceCode":"\n\tprivate int parseSubErrorCode(@Nullable String message) {\n\t\tif (message == null) {\n\t\t\treturn -1;\n\t\t}\n\t\tMatcher matcher = SUB_ERROR_CODE.matcher(message);\n\t\tif (matcher.matches()) {\n\t\t\treturn Integer.parseInt(matcher.group(1), 16);\n\t\t}\n\t\treturn -1;\n\t}\n\n\tprivate void raiseExceptionForErrorCode(int code, NamingException exception) {\n\t\tString hexString = Integer.toHexString(code);\n\t\tThrowable cause = new ActiveDirectoryAuthenticationException(hexString, exception.getMessage(), exception);\n\t\tswitch (code) {\n\t\t\tcase PASSWORD_EXPIRED -> throw new CredentialsExpiredException(this.messages\n\t\t\t\t.getMessage(\"LdapAuthenticationProvider.credentialsExpired\", \"User credentials have expired\"), cause);\n\t\t\tcase ACCOUNT_DISABLED -> throw new DisabledException(\n\t\t\t\t\tthis.messages.getMessage(\"LdapAuthenticationProvider.disabled\", \"User is disabled\"), cause);\n\t\t\tcase ACCOUNT_EXPIRED -> throw new AccountExpiredException(\n\t\t\t\t\tthis.messages.getMessage(\"LdapAuthenticationProvider.expired\", \"User account has expired\"), cause);\n\t\t\tcase ACCOUNT_LOCKED -> throw new LockedException(\n\t\t\t\t\tthis.messages.getMessage(\"LdapAuthenticationProvider.locked\", \"User account is locked\"), cause);\n\t\t\tdefault -> throw badCredentials(cause);\n\t\t}\n\t}\n\n\tprivate String subCodeToLogMessage(int code) {\n\t\treturn switch (code) {\n\t\t\tcase USERNAME_NOT_FOUND -> \"User was not found in directory\";\n\t\t\tcase INVALID_PASSWORD -> \"Supplied password was invalid\";\n\t\t\tcase NOT_PERMITTED -> \"User not permitted to logon at this time\";\n\t\t\tcase PASSWORD_EXPIRED -> \"Password has expired\";\n\t\t\tcase ACCOUNT_DISABLED -> \"Account is disabled\";\n\t\t\tcase ACCOUNT_EXPIRED -> \"Account expired\";\n\t\t\tcase PASSWORD_NEEDS_RESET -> \"User must reset password\";","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java#L249-L285","documentation":"ActiveDirectoryLdapAuthenticationProvider maps AD bind-failure sub-codes to Spring exceptions. When Active Directory reports the account is disabled (bind error 49 with data 533, ACCOUNT_DISABLED), raiseExceptionForErrorCode throws DisabledException('User is disabled') with the ActiveDirectoryAuthenticationException as cause.","triggerScenarios":"authenticate() -> handleBindException() -> raiseExceptionForErrorCode(ACCOUNT_DISABLED), raised when an LDAP bind against AD fails with sub-error code 533 indicating the user account is disabled in Active Directory.","commonSituations":"User left the company and the account was disabled; account administratively disabled pending onboarding/HR action; authenticating with a shared or legacy account that IT disabled.","solutions":["Have an AD administrator enable the account (Set-ADUser -Enabled $true) if access is legitimate.","Confirm you are authenticating with the intended, active account rather than a deprecated one.","Catch DisabledException separately to show an account-specific message instead of a generic login failure.","Verify user search base doesn't resolve to a different, disabled account with the same name."],"exampleFix":"// before\ncatch (BadCredentialsException e) { return \"login?error\"; }\n// after\ncatch (DisabledException e) { model.addAttribute(\"msg\", \"Account disabled; contact IT\"); return \"login\"; }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return authenticationManager.authenticate(token);\n} catch (DisabledException e) {\n    model.addAttribute(\"msg\", \"Account disabled; contact IT\");\n    return \"login\";\n}","preventionTips":["Catch DisabledException separately from BadCredentialsException for distinct UX.","Keep HR-to-IT account deprovisioning in sync to avoid surprise lockouts of legit users.","Log the sub-error hex code from ActiveDirectoryAuthenticationException for diagnostics.","Verify user search base doesn't resolve to a different (disabled) account."],"tags":["ldap","active-directory","disabled-account","spring-security"],"backgroundTag":"permission-denied","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}