{"record":{"id":"30f4df22296c8033","repo":"apereo/cas","slug":"failed-to-authenticate-code","errorCode":null,"errorMessage":"Failed to authenticate code ","messagePattern":"Failed to authenticate code ","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/GoogleAuthenticatorAuthenticationHandler.java","lineNumber":72,"sourceCode":"    public boolean supports(final Credential credential) {\n        return GoogleAuthenticatorTokenCredential.class.isAssignableFrom(credential.getClass());\n    }\n\n    @Override\n    protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws Throwable {\n        val tokenCredential = (GoogleAuthenticatorTokenCredential) credential;\n        val authentication = Objects.requireNonNull(WebUtils.getInProgressAuthentication());\n        Objects.requireNonNull(authentication, \"No authentication is available to determine the principal\");\n        val validatedToken = validator.validate(authentication, tokenCredential);\n        if (validatedToken != null) {\n            val principal = authentication.getPrincipal().getId();\n            LOGGER.debug(\"Validated OTP token [{}] successfully for [{}]\", validatedToken, principal);\n            validator.store(validatedToken);\n            LOGGER.debug(\"Creating authentication result and building principal for [{}]\", principal);\n            return createHandlerResult(tokenCredential, principalFactory.createPrincipal(principal));\n        }\n        LOGGER.warn(\"Authorization of OTP token [{}] has failed\", credential);\n        throw new FailedLoginException(\"Failed to authenticate code \" + credential);\n    }\n}\n","sourceCodeStart":54,"sourceCodeEnd":75,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/GoogleAuthenticatorAuthenticationHandler.java#L54-L75","documentation":"GoogleAuthenticatorAuthenticationHandler could not validate the submitted OTP token. GoogleAuthenticatorOneTimeTokenCredentialValidator returned null (token invalid, already used, wrong secret, or account mismatch) so the handler logs a warning and throws FailedLoginException. It means the user-entered TOTP/scratch code did not authorize against any registered GAuth account.","triggerScenarios":"doAuthentication calls validator.validate(tokenCredential, authentication); when the returned validatedToken is null (no authorized account matched, token reused, account not found, clock drift past window) the handler throws FailedLoginException(\"Failed to authenticate code \" + credential).","commonSituations":"User types an expired or already-consumed code; phone/server clock drift exceeding the allowed window; wrong secret registered for the account; user entering a TOTP from a different account when multiple accounts exist without specifying accountId.","solutions":["Have the user generate a fresh code from the authenticator app and retry — reused codes are rejected by tokenRepository.exists(uid, otp)","Verify time sync (NTP) on the CAS server; large clock drift invalidates TOTP codes","Check the registered account record's secretKey matches the QR code the user scanned","If multiple accounts exist for the user, supply the correct accountId on the credential"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// client-side sanity before submit\nif (!/^\\d{6}$/.test(otp) && !/^\\d{8}$/.test(otp)) reject(\"OTP must be 6 or 8 digits\");","typeGuard":null,"tryCatchPattern":"try {\n    result = handler.authenticate(tokenCredential);\n} catch (FailedLoginException e) {\n    return failure(\"Invalid or expired code — generate a new one and retry\");\n}","preventionTips":["Keep CAS server clocks NTP-synchronized","Never accept the same OTP twice in your UI flow","Ensure users scan the QR for the exact account they authenticate as","Prompt users to wait for a new 30-second window after failures"],"tags":["gauth","otp","totp","mfa"],"backgroundTag":"authentication-failed","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"}