spring-projects/spring-security · error · DisabledException
AccountStatusUserDetailsChecker.disabled
AccountStatusUserDetailsChecker.disabled
Error message
User is disabled
What it means
AccountStatusUserDetailsChecker.check() validates a UserDetails after authentication. When UserDetails.isEnabled() returns false it throws DisabledException with message 'User is disabled'. This indicates the user account exists but is flagged as not enabled.
Solutions
- Enable the account: set the enabled flag to true in your user store or make isEnabled() return true in your UserDetails implementation
- If activation is required, implement an activation flow that flips the enabled flag after verification
- If the flag is loaded incorrectly, fix your UserDetailsService SQL/mapping so the enabled column is read properly
- Catch DisabledException in an AuthenticationFailureHandler and show a 'contact administrator / activate account' message
Example fix
// before
@Override
public boolean isEnabled() { return false; }
// after
@Override
public boolean isEnabled() { return this.enabled; } // persisted activation flag Defensive patterns
Strategy: try-catch
Validate before calling
UserDetails user = uds.loadUserByUsername(username);
if (!user.isEnabled()) { throw new IllegalStateException("Account not activated: " + username); } Type guard
boolean isLoginAllowed(UserDetails u) { return u.isEnabled(); } Try / catch
try { authMgr.authenticate(token); } catch (DisabledException e) { return ResponseEntity.status(403).body("Account is disabled. Please activate or contact support."); } Prevention
- Always persist and load an explicit enabled flag
- Run the account-status checker in tests against representative users
- Catch DisabledException separately from BadCredentialsException for clear UX
When it happens
Trigger: DaoAuthenticationProvider (or any AuthenticationProvider using this checker) authenticates a user whose UserDetails.isEnabled() returns false.
Common situations: Newly registered users whose account requires email activation; admins disabling accounts; user records loaded from a DB column like enabled=0; custom UserDetailsService returning UserDetails with enabled hardcoded false.
Related errors
- User is disabled
- AbstractUserDetailsAuthenticationProvider.disabled
- AccountStatusUserDetailsChecker.expired
- An Authentication object was not found in the…
- Authenticated principal required to operate with ACLs
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/68193edd01ab3c75.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java:51
*
* @author Luke Taylor
*/
public class AccountStatusUserDetailsChecker implements UserDetailsChecker, MessageSourceAware {
private final Log logger = LogFactory.getLog(getClass());
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
@Override
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
this.logger.debug("Failed to authenticate since user account is locked");
throw new LockedException(
this.messages.getMessage("AccountStatusUserDetailsChecker.locked", "User account is locked"));
}
if (!user.isEnabled()) {
this.logger.debug("Failed to authenticate since user account is disabled");
throw new DisabledException(
this.messages.getMessage("AccountStatusUserDetailsChecker.disabled", "User is disabled"));
}
if (!user.isAccountNonExpired()) {
this.logger.debug("Failed to authenticate since user account is expired");
throw new AccountExpiredException(
this.messages.getMessage("AccountStatusUserDetailsChecker.expired", "User account has expired"));
}
if (!user.isCredentialsNonExpired()) {
this.logger.debug("Failed to authenticate since user account credentials have expired");
throw new CredentialsExpiredException(this.messages
.getMessage("AccountStatusUserDetailsChecker.credentialsExpired", "User credentials have expired"));
}
}
/**
* Sets the {@link MessageSource} used to resolve exception messages.
* @since 5.2
*/View on GitHub (pinned to 96852e8860)