apereo/cas · error · MultifactorAuthenticationFailedException

Failed to authenticate code

Error message

Failed to authenticate code 

What it means

CasSimpleMultifactorAuthenticationHandler.doAuthentication validates the MFA token credential against the simple MFA service and then compares the token's principal with the currently active authentication principal. On any validation failure or mismatch, it throws MultifactorAuthenticationFailedException "Failed to authenticate code <id>". It means the supplied one-time MFA code/ticket is not usable for this authentication attempt.

Solutions

  1. Request and submit a fresh MFA code within its validity window in the same session
  2. Ensure the same authenticated principal completes the MFA step (no account switch mid-flow)
  3. Verify all CAS nodes share the same ticket registry so tokens issued on one node validate on another
  4. Check throttling configuration/bucket limits if users are being locked out by retry volume
Defensive patterns

Strategy: retry

Try / catch

try {
    handlerResult = authenticationHandler.authenticate(transaction);
} catch (MultifactorAuthenticationFailedException e) {
    // discard the stale/foreign code and re-enter the MFA flow to get a fresh one
    mfaRelayService.requestNewCode(activePrincipal);
}

Prevention

When it happens

Trigger: doAuthentication -> multifactorAuthenticationService.validate(...) throwing (missing principal on ticket, principal mismatch, throttled attempts) or the returned principal not equaling findActivePrincipal(), e.g. the code was issued to a different user or was already consumed/expired.

Common situations: User submits an expired or already-used MFA code; code generated in one browser/session but submitted from another login (principal mismatch); clustered deployments where the ticket registry is not shared so the token cannot be found; throttling after repeated wrong codes.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/934fb319bc348f92. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-simple-mfa-core/src/main/java/org/apereo/cas/mfa/simple/CasSimpleMultifactorAuthenticationHandler.java:75

    @Override
    public boolean supports(final Class<? extends Credential> clazz) {
        return CasSimpleMultifactorTokenCredential.class.isAssignableFrom(clazz);
    }

    @Override
    protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential,
                                                                    final Service service) throws Exception {
        return FunctionUtils.doAndThrow(() -> {
            val tokenCredential = (CasSimpleMultifactorTokenCredential) credential;
            val credentialPrincipal = multifactorAuthenticationService.fetch(tokenCredential);
            val resolvedPrincipal = resolvePrincipal(applicationContext, credentialPrincipal);
            val principal = multifactorAuthenticationService.validate(resolvedPrincipal, tokenCredential);

            val activePrincipal = findActivePrincipal();
            if (!principal.equals(activePrincipal)) {
                LOGGER.warn("Credential principal [{}] does not match authentication principal [{}]",
                    principal.getId(), activePrincipal.getId());
                throw new MultifactorAuthenticationFailedException("Failed to authenticate code " + tokenCredential.getId());
            }
            return createHandlerResult(tokenCredential, principal);
        }, MultifactorAuthenticationFailedException::new);
    }

    protected Principal findActivePrincipal() {
        val authentication = Objects.requireNonNull(WebUtils.getInProgressAuthentication());
        val principal = authentication.getPrincipal();
        return principal.getOwner();
    }
}

View on GitHub (pinned to e7288fc434)