apereo/cas · error
Unable to determine google authenticator token credential
Error message
Unable to determine google authenticator token credential
What it means
The same action next fetches the GoogleAuthenticatorTokenCredential from the request context. If no credential was submitted (token form not filled or bound) the action logs this warning, adds an error message, and returns error(). A related guard also rejects credentials whose accountId does not match the selected account.
Solutions
- Ensure the token input field is submitted (non-empty) so the credential is created and bound in the prior flow state
- Re-select the correct device so the credential's accountId matches the account loaded into scope
- Check the MFA webflow form binding/bean configuration so GoogleAuthenticatorTokenCredential is instantiated from the request
- Perform the login through the normal webflow (not direct requests) so scope and credential are populated
Example fix
// before: skipping the token field // POST ...token= (empty) // after: always submit a fresh 6-digit code bound to the selected device // POST ... token=123456&accountId=42
Defensive patterns
Strategy: validation
Validate before calling
GoogleAuthenticatorTokenCredential cred =
WebUtils.getCredential(requestContext, GoogleAuthenticatorTokenCredential.class);
boolean ready = cred != null
&& cred.getToken() != null && cred.getToken().matches("\\d{6}")
&& cred.getAccountId() != null; Try / catch
Event e = action.execute(requestContext);
if ("error".equals(e.getId())) {
// re-render the token form so a credential is bound on resubmit
} Prevention
- Require the token field (server-side and client-side) before submission
- Check form binding configuration for GoogleAuthenticatorTokenCredential
- Ensure the submitted accountId matches the selected device
- Block direct requests that bypass webflow state population
When it happens
Trigger: doExecuteInternal runs with WebUtils.getCredential(requestContext, GoogleAuthenticatorTokenCredential.class) returning null — the credential was never created because the token field was empty or the prior state did not bind it; also when credential.getAccountId() is null or != account.getId().
Common situations: User submits the MFA form without entering a code; form binding misconfigured so GoogleAuthenticatorTokenCredential is not instantiated; user switched selected device but the submitted credential still references the old accountId; direct POST to the endpoint bypassing the flow.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unknown Duo Security authentication attempt
- State [ : : ] does not have a matching transition for
- Failed to authenticate code
- Unauthorized account registration attempt for id
- Failed to authenticate code
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/3f6ab4e34d68a13d.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorValidateSelectedRegistrationAction.java:47
}
@Override
protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {
if (MultifactorAuthenticationTrustUtils.isMultifactorAuthenticationTrustedInScope(requestContext)) {
val trustedDevice = MultifactorAuthenticationTrustUtils.getMultifactorAuthenticationTrustRecord(requestContext, MultifactorAuthenticationTrustRecord.class).orElseThrow();
LOGGER.info("Multifactor authentication device [{}] is trusted with fingerprint [{}]", trustedDevice.getName(), trustedDevice.getDeviceFingerprint());
return success(trustedDevice);
}
val account = MultifactorAuthenticationWebflowUtils.getOneTimeTokenAccount(requestContext, OneTimeTokenAccount.class);
if (account == null) {
LOGGER.warn("Unable to determine google authenticator account");
addErrorMessageToContext(requestContext);
return error();
}
val credential = WebUtils.getCredential(requestContext, GoogleAuthenticatorTokenCredential.class);
if (credential == null) {
LOGGER.warn("Unable to determine google authenticator token credential");
addErrorMessageToContext(requestContext);
return error();
}
LOGGER.trace("Located account [{}] to be used for credential [{}]", account, credential);
if (credential.getAccountId() == null || credential.getAccountId() != account.getId()) {
LOGGER.warn("Google authenticator token credential is not assigned a valid account id");
addErrorMessageToContext(requestContext);
return error();
}
return null;
}
}
View on GitHub (pinned to e7288fc434)