apereo/cas · error · AuthenticationException
Request is assigned an invalid device identifier
Error message
Request is assigned an invalid device identifier
What it means
AuthenticationException thrown by DefaultQRAuthenticationTokenValidatorService.validate when the device id claim (QR_AUTHENTICATION_DEVICE_ID) in the QR token does not match the device id presented in the validation request. The token is bound to the device that originally requested the QR code.
Solutions
- Display a fresh QR code on the requesting device and scan it from that same device/session.
- Ensure the client persists and consistently sends the same device id between QR generation and validation.
- Verify no middleware/browser privacy settings regenerate the device identifier mid-flow.
- Check that QR generation and validation use the same device id source (cookie/local storage key) in custom frontends.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the request carries the same device id as the token
String tokenDeviceId = claims.getClaim(QR_AUTHENTICATION_DEVICE_ID, String.class);
if (tokenDeviceId != null && !tokenDeviceId.equalsIgnoreCase(requestDeviceId)) {
return error("device mismatch; regenerate QR code");
} Try / catch
try { validatorService.validate(request); } catch (AuthenticationException e) { if (e.getMessage().contains("invalid device identifier")) { return regenerateQrEvent(); } throw e; } Prevention
- Persist the device id stably (cookie/localStorage) across the QR flow.
- Generate the QR code and validate on the same device/session.
- Avoid privacy tooling or middleware that rotates device identifiers mid-session.
When it happens
Trigger: Strings.CI.equals(tokenDeviceId, request.getDeviceId()) is false during QR token validation — request.getDeviceId() differs from the device id embedded in the JWT at mint time.
Common situations: User scans the QR code with a different device/browser profile than the one that displayed it; device id regenerated after cookies/storage cleared; multiple devices sharing a session with stale QR codes; device id not passed through correctly by the client integration.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Token has expired
- Token does not belong to the assigned principal
- Token has an invalid issuer that does not match
- Unable to accept the ID token with an invalid [sub] claim
- Unknown authorization header type
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/e71a3477fa34cafa.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-qr-authentication/src/main/java/org/apereo/cas/qr/validation/DefaultQRAuthenticationTokenValidatorService.java:66
val authentication = tgt.getAuthentication();
LOGGER.trace("Authentication attempt linked to [{}] is [{}]", tgt.getId(), authentication);
if (!authentication.getPrincipal().getId().equals(claims.getSubject())) {
val message = String.format("Token %s does not belong to the assigned principal", claims.getSubject());
throw new AuthenticationException(message);
}
if (!claims.getIssuer().equals(casProperties.getServer().getPrefix())) {
val message = String.format("Token %s has an invalid issuer %s that does not match %s", tgt.getId(),
claims.getIssuer(), casProperties.getServer().getPrefix());
throw new AuthenticationException(message);
}
val tokenDeviceId = FunctionUtils.doUnchecked(() -> claims.getStringClaim(QRAuthenticationConstants.QR_AUTHENTICATION_DEVICE_ID));
if (!Strings.CI.equals(tokenDeviceId, request.getDeviceId())) {
LOGGER.warn("Request device identifier [{}] does not match the token's identifier: [{}]", request.getDeviceId(), tokenDeviceId);
throw new AuthenticationException("Request is assigned an invalid device identifier");
}
if (!deviceRepository.isAuthorizedDeviceFor(request.getDeviceId(), claims.getSubject())) {
val message = String.format("Token is not authorized for device identifier [%s]", request.getDeviceId());
throw new AuthenticationException(message);
}
return QRAuthenticationTokenValidationResult.builder()
.authentication(authentication)
.build();
}
}
View on GitHub (pinned to e7288fc434)