{"record":{"id":"8557facf2d3a257f","repo":"apereo/cas","slug":"unable-to-determine-google-authenticator-account","errorCode":null,"errorMessage":"Unable to determine google authenticator account","messagePattern":"Unable to determine google authenticator account","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorValidateSelectedRegistrationAction.java","lineNumber":41,"sourceCode":"@Slf4j\npublic class GoogleAuthenticatorValidateSelectedRegistrationAction extends BaseCasWebflowAction {\n    private static final String CODE = \"screen.authentication.gauth.invalid\";\n\n    private static void addErrorMessageToContext(final RequestContext requestContext) {\n        WebUtils.addErrorMessageToContext(requestContext, CODE);\n    }\n\n    @Override\n    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {\n        if (MultifactorAuthenticationTrustUtils.isMultifactorAuthenticationTrustedInScope(requestContext)) {\n            val trustedDevice = MultifactorAuthenticationTrustUtils.getMultifactorAuthenticationTrustRecord(requestContext, MultifactorAuthenticationTrustRecord.class).orElseThrow();\n            LOGGER.info(\"Multifactor authentication device [{}] is trusted with fingerprint [{}]\", trustedDevice.getName(), trustedDevice.getDeviceFingerprint());\n            return success(trustedDevice);\n        }\n\n        val account = MultifactorAuthenticationWebflowUtils.getOneTimeTokenAccount(requestContext, OneTimeTokenAccount.class);\n        if (account == null) {\n            LOGGER.warn(\"Unable to determine google authenticator account\");\n            addErrorMessageToContext(requestContext);\n            return error();\n        }\n        val credential = WebUtils.getCredential(requestContext, GoogleAuthenticatorTokenCredential.class);\n        if (credential == null) {\n            LOGGER.warn(\"Unable to determine google authenticator token credential\");\n            addErrorMessageToContext(requestContext);\n            return error();\n        }\n        LOGGER.trace(\"Located account [{}] to be used for credential [{}]\", account, credential);\n        if (credential.getAccountId() == null || credential.getAccountId() != account.getId()) {\n            LOGGER.warn(\"Google authenticator token credential is not assigned a valid account id\");\n            addErrorMessageToContext(requestContext);\n            return error();\n        }\n        return null;\n    }\n}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorValidateSelectedRegistrationAction.java#L23-L59","documentation":"GoogleAuthenticatorValidateSelectedRegistrationAction retrieves the previously selected OneTimeTokenAccount from the webflow request context. When it is absent the action logs this warning, adds an error message, and returns error() so the MFA validation step cannot proceed.","triggerScenarios":"doExecuteInternal runs but MultifactorAuthenticationWebflowUtils.getOneTimeTokenAccount(...) returns null: the user reached the validate-selected-registration state without having selected a registered device in the prior flow step (direct navigation, expired/lost flow scope, or repository lookup returned nothing).","commonSituations":"User bookmarks or re-submits the token entry page after the flow state expired; session loss between device-selection and token-entry steps; the selected registrationId no longer resolves (device deleted concurrently); custom flows skipping the selection state.","solutions":["Restart the MFA login flow and select a registered device before entering the token","Check that the token repository actually contains an account for the user (registration completed and persisted)","Avoid reusing stale webflow executions; start a fresh login attempt","If customizing the flow, ensure the selection state stores the account into flow scope before this action runs"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// before the validate-selected step, confirm an account is in scope\nOneTimeTokenAccount acct =\n    MultifactorAuthenticationWebflowUtils.getOneTimeTokenAccount(requestContext, OneTimeTokenAccount.class);\nboolean ready = acct != null;","typeGuard":null,"tryCatchPattern":"Event e = action.execute(requestContext);\nif (\"error\".equals(e.getId())) {\n    // route user back to device selection to repopulate the account\n}","preventionTips":["Always pass through device selection before token entry","Verify the token repository holds the user's registered device","Avoid stale webflow executions/bookmarks","Keep flow scope populated when customizing the MFA flow"],"tags":["webflow","mfa","account","state"],"backgroundTag":"missing-required-argument","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}