apereo/cas · warning
Unable to authorize given token
Error message
Unable to authorize given token [{}] for account [{}] What it means
GoogleAuthenticatorSaveRegistrationAction.validate() checks the submitted token via validator.isTokenAuthorizedFor(token, account). If not authorized it logs this warning and returns false, so the registration save (new secret/token store entry) is refused.
Solutions
- Have the user enter a new code generated immediately after scanning the QR code for this specific account
- Verify the account object passed to validate() matches the QR code that was scanned (same username/secret)
- Synchronize clocks and, if needed, widen the token validation window in cas.authn.mfa.gauth.* settings
- Retry the registration flow to regenerate a fresh secret and QR code
Defensive patterns
Strategy: retry
Validate before calling
boolean codeLooksValid = code != null && code.matches("\\d{6}");
// confirm account/secret freshly provisioned before validate() Try / catch
boolean ok = action.validate(token, account);
if (!ok) {
// retry registration with a newly generated secret/QR
} Prevention
- Enter the first code right after scanning the QR
- Match the app entry to the account being registered
- Sync clocks; widen validation window if drift is common
- Regenerate the secret when repeated validation fails
When it happens
Trigger: validate() invoked with a token that does not validate against the given account's secret — wrong code typed during registration, expired window, or token not for this account; the fallback function also yields false on exceptions.
Common situations: User enters a code from a different account's entry in their authenticator app; delay between QR scan and code entry exceeds the window; server clock drift; duplicated registration attempts consuming tokens.
Related errors
- OTP format is invalid
- Authorization of OTP token
- Failed to authenticate code
- cannot be found in the registry
- cannot reuse OTP
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/c957e991e0a7f7c6.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorSaveRegistrationAction.java:54
final OneTimeTokenCredentialRepository repository,
final CasConfigurationProperties casProperties,
final OneTimeTokenCredentialValidator<GoogleAuthenticatorTokenCredential, GoogleAuthenticatorToken> validator,
final TenantExtractor tenantExtractor) {
super(repository, casProperties, tenantExtractor);
this.validator = validator;
}
@Override
protected boolean validate(final GoogleAuthenticatorAccount account, final RequestContext requestContext) {
return FunctionUtils.doAndHandle(_ -> {
val token = requestContext.getRequestParameters().getRequiredInteger(REQUEST_PARAMETER_TOKEN);
if (validator.isTokenAuthorizedFor(token, account)) {
LOGGER.debug("Successfully validated token [{}]", token);
val googleAuthenticatorToken = new GoogleAuthenticatorToken(token, account.getUsername());
validator.getTokenRepository().store(googleAuthenticatorToken);
return true;
}
LOGGER.warn("Unable to authorize given token [{}] for account [{}]", token, account);
return false;
}, e -> false)
.apply(account);
}
@Override
protected Event getErrorEvent(final RequestContext requestContext) {
val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(requestContext);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return error();
}
@Override
protected GoogleAuthenticatorAccount buildOneTimeTokenAccount(final RequestContext requestContext) {
val acct = super.buildOneTimeTokenAccount(requestContext);
return GoogleAuthenticatorAccount.from(acct);
}
}View on GitHub (pinned to e7288fc434)