apereo/cas · error · FailedLoginException

Unable to verify QR code

Error message

Unable to verify QR code 

What it means

FailedLoginException thrown by QRAuthenticationTokenAuthenticationHandler.doAuthentication after any exception occurs while validating the QR token credential. The handler delegates to QRAuthenticationTokenValidatorService.validate; on failure it logs the cause and always throws this FailedLoginException carrying the credential id.

Solutions

  1. Regenerate/refresh the QR code and scan it promptly (check the token TTL in QR authentication properties).
  2. Read the logged underlying exception (LoggingUtils.error output) to identify the exact validation failure.
  3. Confirm cas.server.prefix matches the issuer used when the QR token was minted.
  4. Verify the device id is still authorized (deviceRepository) and that ticketRegistry is shared/healthy in clustered deployments.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate token freshness client-side before submitting
boolean expired = Instant.now().isAfter(tokenExpiryInstant);
if (expired) { refreshQrCode(); }

Try / catch

try { handler.authenticate(qrTokenCredential); } catch (FailedLoginException e) { LOGGER.warn("QR login rejected: {}", e.getMessage()); return errorEvent("qr.login.failed"); }

Prevention

When it happens

Trigger: A QR login token credential fails validation: token expired, token's TGT no longer in the ticket registry, principal/issuer/device-id mismatch, device not authorized, or the JWT itself is malformed/untrusted — any Exception inside tokenValidatorService.validate(request) leads here.

Common situations: User scans an expired QR code; TGT expired and evicted from ticketRegistry; CAS server prefix changed so issuer no longer matches; device re-registered/deauthorized; clock skew between nodes; token from a different CAS environment.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-qr-authentication/src/main/java/org/apereo/cas/qr/authentication/QRAuthenticationTokenAuthenticationHandler.java:63

    @Override
    protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws GeneralSecurityException {
        val tokenCredential = (QRAuthenticationTokenCredential) credential;
        try {
            LOGGER.debug("Received token [{}]", tokenCredential.getId());

            val request = QRAuthenticationTokenValidationRequest.builder()
                .token(tokenCredential.getId())
                .registeredService(Optional.empty())
                .deviceId(tokenCredential.getDeviceId())
                .build();

            val result = tokenValidatorService.validate(request);
            val principal = result.getAuthentication().getPrincipal();
            return createHandlerResult(tokenCredential, principal);
        } catch (final Exception e) {
            LoggingUtils.error(LOGGER, e);
        }
        throw new FailedLoginException("Unable to verify QR code " + tokenCredential.getId());
    }
}

View on GitHub (pinned to e7288fc434)