apereo/cas · warning · AccountDisabledException

Account has been disabled

Error message

Account has been disabled

What it means

QueryDatabaseAuthenticationHandler throws AccountDisabledException('Account has been disabled') when the row's column named by properties.getFieldDisabled() is truthy (BooleanUtils.toBoolean true or '1'). The credential check already passed; the account record is flagged disabled.

Solutions

  1. Re-enable the account in the database (set the flag to 0/false)
  2. Verify fieldDisabled maps to the intended status column
  3. Trace the provisioning job that set the flag if disabling was unexpected
  4. Update the flag in the system of record so the next sync does not re-disable

Example fix

// before: fieldDisabled bound to always-1 column
// cas.authn.jdbc.query[0].fieldDisabled=user_type
// after
// cas.authn.jdbc.query[0].fieldDisabled=account_disabled
Defensive patterns

Strategy: try-catch

Validate before calling

Map<String,Object> row = jdbc.queryForMap(sql, user);
Object flag = row.get("account_disabled");
boolean disabled = flag != null && ("1".equals(flag.toString()) || BooleanUtils.toBoolean(flag.toString()));
if (disabled) return showAccountDisabledPage(user);

Type guard

boolean isTruthyFlag(Object v) { return v != null && ("1".equals(v.toString()) || BooleanUtils.toBoolean(v.toString())); }

Try / catch

try {
    authResult = handler.authenticate(credential);
} catch (AccountDisabledException e) {
    // credentials valid; account administratively disabled
    return showAccountDisabledNotice(user);
}

Prevention

When it happens

Trigger: dbFields contains the disabled-field column configured via cas.authn.jdbc.query[0].fieldDisabled and its value parses as a truthy boolean or the string "1".

Common situations: Admin-deactivated accounts, identity/HR sync flagging users, fieldDisabled accidentally mapped to a boolean-ish column that is 1 for all rows (e.g. 'locked' or a type flag).

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/637d693cf8029368. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java:86

                    throw new FailedLoginException("Missing field 'total' from the query results for " + username);
                }

                val count = dbFields.get("total");
                if (count == null || !NumberUtils.isCreatable(count.toString())) {
                    throw new FailedLoginException("Missing field value 'total' from the query results for "
                        + username + " or value not parseable as a number");
                }

                val number = NumberUtils.createNumber(count.toString());
                if (number.longValue() != 1) {
                    throw new FailedLoginException("No records found for user " + username);
                }
            }

            if (StringUtils.isNotBlank(properties.getFieldDisabled()) && dbFields.containsKey(properties.getFieldDisabled())) {
                val dbDisabled = dbFields.get(properties.getFieldDisabled()).toString();
                if (BooleanUtils.toBoolean(dbDisabled) || "1".equals(dbDisabled)) {
                    throw new AccountDisabledException("Account has been disabled");
                }
            }
            if (StringUtils.isNotBlank(properties.getFieldExpired()) && dbFields.containsKey(properties.getFieldExpired())) {
                val dbExpired = dbFields.get(properties.getFieldExpired()).toString();
                if (BooleanUtils.toBoolean(dbExpired) || "1".equals(dbExpired)) {
                    throw new AccountPasswordMustChangeException("Password has expired");
                }
            }

            val attributes = collectPrincipalAttributes(dbFields);
            val principal = this.principalFactory.createPrincipal(username, attributes);
            return createHandlerResult(credential, principal, new ArrayList<>());

        } catch (final IncorrectResultSizeDataAccessException e) {
            if (e.getActualSize() == 0) {
                throw new AccountNotFoundException(username + " not found with SQL query");
            }
            throw new FailedLoginException("Multiple records found for " + username);

View on GitHub (pinned to e7288fc434)