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.

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)

Solutions

  1. Enable the account: set the enabled flag to true in your user store or make isEnabled() return true in your UserDetails implementation
  2. If activation is required, implement an activation flow that flips the enabled flag after verification
  3. If the flag is loaded incorrectly, fix your UserDetailsService SQL/mapping so the enabled column is read properly
  4. 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

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


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