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
- Regenerate/refresh the QR code and scan it promptly (check the token TTL in QR authentication properties).
- Read the logged underlying exception (LoggingUtils.error output) to identify the exact validation failure.
- Confirm cas.server.prefix matches the issuer used when the QR token was minted.
- 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
- Auto-refresh the QR image before its token expires.
- Keep server clocks NTP-synchronized.
- Keep cas.server.prefix stable; monitor the validator's logged root cause.
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
- Authentication handler is disabled
- No user can be accepted because none is defined
- not found in backing map.
- Unable to authenticate
- No authentication handlers could be resolved to support the…
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)