{"record":{"id":"211980add8d842eb","repo":"apereo/cas","slug":"token-has-exceeded-the-maximum-number-of-atte","errorCode":null,"errorMessage":"Token [{}] has exceeded the maximum number of attempts [{}]","messagePattern":"Token \\[(.+?)\\] has exceeded the maximum number of attempts \\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorAuthorizeTokenAttemptAction.java","lineNumber":39,"sourceCode":"@Slf4j\npublic class GoogleAuthenticatorAuthorizeTokenAttemptAction extends BaseCasWebflowAction {\n    private static final String FLOW_SCOPE_ATTEMPT_COUNTER = \"GoogleAuthenticatorTokenAttemptCount\";\n    \n    private final CasConfigurationProperties casProperties;\n\n    @Override\n    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {\n        val maxAllowedAttempts = casProperties.getAuthn().getMfa().getGauth().getCore().getMaximumAuthenticationAttempts();\n        val credential = Objects.requireNonNull(WebUtils.getCredential(requestContext));\n        var attemptCounter = requestContext.getFlowScope().get(FLOW_SCOPE_ATTEMPT_COUNTER, Integer.class, 0);\n        LOGGER.debug(\"Attempt counter for token [{}] is [{}]\", credential.getId(), attemptCounter);\n        if (maxAllowedAttempts <= 0 || attemptCounter < maxAllowedAttempts) {\n            LOGGER.debug(\"Token [{}] is allowed to proceed with authentication\", credential.getId());\n            attemptCounter++;\n            requestContext.getFlowScope().put(FLOW_SCOPE_ATTEMPT_COUNTER, attemptCounter);\n            return success(attemptCounter);\n        }\n        LOGGER.warn(\"Token [{}] has exceeded the maximum number of attempts [{}]\", credential.getId(), attemptCounter);\n        return error();\n    }\n}\n","sourceCodeStart":21,"sourceCodeEnd":43,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/web/flow/GoogleAuthenticatorAuthorizeTokenAttemptAction.java#L21-L43","documentation":"GoogleAuthenticatorAuthorizeTokenAttemptAction limits how many times a token can be submitted for verification within a webflow session. When the stored attemptCounter reaches maxAllowedAttempts (maxCheckAttempts minus allowed margin logic in the source), it warns 'Token [{}] has exceeded the maximum number of attempts [{}]' and returns an error event, blocking further attempts for that credential.","triggerScenarios":"A user (or an automated script) submits an incorrect Google Authenticator OTP credential to the webflow more times than the configured maximum during one authentication flow session.","commonSituations":"Brute-force attempts on OTP codes, users repeatedly mistyping codes, or very low maxCheckAttempts configuration making legitimate users hit the cap; token id in the log identifies the credential.","solutions":["Increase cas.authn.mfa.gauth.max-check-attempts (or core token attempt settings) if legitimate users hit the cap","Start a new authentication flow (restart the webflow) which resets the flow-scope attempt counter","Investigate the repeated attempts in the log for brute-force patterns and consider rate limiting","Verify the user's authenticator app clock drift if failures are legitimate"],"exampleFix":"// before\ncas.authn.mfa.gauth.max-check-attempts=1\n// after\ncas.authn.mfa.gauth.max-check-attempts=5","handlingStrategy":"validation","validationCode":"if (attemptCounter >= maxCheckAttempts) {\n    return error(); // caller-side check before submitting another token\n}","typeGuard":null,"tryCatchPattern":"try { ... } catch (Exception e) { /* this is a webflow event, not exception; handle the 'error' transition by restarting the flow */ }","preventionTips":["Set max-check-attempts to a sane value (3-5)","Educate users the flow locks after N bad codes","Rate-limit OTP submissions server-side","Check authenticator clock drift to reduce legitimate failures"],"tags":["mfa","gauth","otp","rate-limit"],"backgroundTag":"rate-limit-exceeded","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"}