{"record":{"id":"385c28ceb4a1d986","repo":"spring-projects/spring-security","slug":"abstractuserdetailsauthenticationprovider-disabled","errorCode":"AbstractUserDetailsAuthenticationProvider.disabled","errorMessage":"User is disabled","messagePattern":"User is disabled","errorType":"exception","errorClass":"DisabledException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java","lineNumber":82,"sourceCode":"\tprivate ReactiveUserDetailsPasswordService userDetailsPasswordService = ReactiveUserDetailsPasswordService.NOOP;\n\n\tprivate Scheduler scheduler = Schedulers.boundedElastic();\n\n\tprivate UserDetailsChecker preAuthenticationChecks = this::defaultPreAuthenticationChecks;\n\n\tprivate UserDetailsChecker postAuthenticationChecks = this::defaultPostAuthenticationChecks;\n\n\tprivate @Nullable ReactiveCompromisedPasswordChecker compromisedPasswordChecker;\n\n\tprivate void defaultPreAuthenticationChecks(UserDetails user) {\n\t\tif (!user.isAccountNonLocked()) {\n\t\t\tthis.logger.debug(\"User account is locked\");\n\t\t\tthrow new LockedException(this.messages.getMessage(\"AbstractUserDetailsAuthenticationProvider.locked\",\n\t\t\t\t\t\"User account is locked\"));\n\t\t}\n\t\tif (!user.isEnabled()) {\n\t\t\tthis.logger.debug(\"User account is disabled\");\n\t\t\tthrow new DisabledException(\n\t\t\t\t\tthis.messages.getMessage(\"AbstractUserDetailsAuthenticationProvider.disabled\", \"User is disabled\"));\n\t\t}\n\t\tif (!user.isAccountNonExpired()) {\n\t\t\tthis.logger.debug(\"User account is expired\");\n\t\t\tthrow new AccountExpiredException(this.messages\n\t\t\t\t.getMessage(\"AbstractUserDetailsAuthenticationProvider.expired\", \"User account has expired\"));\n\t\t}\n\t}\n\n\tprivate void defaultPostAuthenticationChecks(UserDetails user) {\n\t\tif (!user.isCredentialsNonExpired()) {\n\t\t\tthis.logger.debug(\"User account credentials have expired\");\n\t\t\tthrow new CredentialsExpiredException(this.messages.getMessage(\n\t\t\t\t\t\"AbstractUserDetailsAuthenticationProvider.credentialsExpired\", \"User credentials have expired\"));\n\t\t}\n\t}\n\n\t@Override","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java#L64-L100","documentation":"defaultPreAuthenticationChecks in AbstractUserDetailsReactiveAuthenticationManager throws DisabledException with 'User is disabled' (message code AbstractUserDetailsAuthenticationProvider.disabled) when UserDetails.isEnabled() returns false. The account exists but is flagged disabled, so authentication fails before credential checking.","triggerScenarios":"authenticate() receiving a UserDetails with isEnabled() == false — e.g. users.enabled=0 in the database, or a custom UserDetails class that does not override isEnabled() (interface default returns false).","commonSituations":"Newly registered users pending email verification; admin-deactivated accounts; custom UserDetails implementations forgetting to implement isEnabled(); schema migrations zeroing the enabled column.","solutions":["Set the enabled flag true in your user store, or override isEnabled() to return true when appropriate","Complete whatever activation flow (email verification) gates the enabled flag","Catch DisabledException in the reactive chain and show an account-disabled message","Verify your UserDetails implementation implements isEnabled() rather than relying on interface defaults"],"exampleFix":"// before\nclass AppUser implements UserDetails { /* isEnabled() not overridden -> false */ }\n// after\nclass AppUser implements UserDetails {\n  @Override public boolean isEnabled() { return this.active; }\n}","handlingStrategy":"try-catch","validationCode":"if (!userDetails.isEnabled()) throw new DisabledException(\"Account disabled: \" + username);","typeGuard":"boolean loginAllowed(UserDetails u) { return u.isEnabled(); }","tryCatchPattern":"authManager.authenticate(token)\n  .onErrorResume(DisabledException.class, e -> Mono.error(new AuthFailure(\"ACCOUNT_DISABLED\")));","preventionTips":["Override isEnabled() in custom UserDetails implementations","Gate enabled flag behind a completed activation flow","Seed test users with enabled=true","Keep enabled column default consistent with business rules"],"tags":["authentication","reactive","account-disabled","userdetails"],"backgroundTag":"authentication-required","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"}