apereo/cas · error · InvalidCibaRequestException
Backchannel token delivery mode cannot grant access tokens
Error message
Backchannel token delivery mode cannot grant access tokens
What it means
AccessTokenCibaGrantRequestExtractor.extractRequest throws InvalidCibaRequestException with this message when the registered service's backchannelTokenDeliveryMode parses to something other than POLL or PING. Only those modes can complete a CIBA grant at the token endpoint, so CAS refuses the access-token grant.
Solutions
- Set the service's backchannelTokenDeliveryMode to 'poll' or 'ping'
- If PUSH delivery is required, implement/use the push notification path instead of polling the token endpoint
- Note valueOf on an unknown mode string throws IllegalArgumentException before this check — ensure the value is a valid OidcBackchannelTokenDeliveryModes constant
Example fix
// before (service definition) "backchannelTokenDeliveryMode": "push" // after "backchannelTokenDeliveryMode": "poll"
Defensive patterns
Strategy: validation
Validate before calling
var mode = service.getBackchannelTokenDeliveryMode();
if (!"poll".equalsIgnoreCase(mode) && !"ping".equalsIgnoreCase(mode)) {
throw new IllegalStateException("CIBA token grant requires delivery mode poll|ping, got: " + mode);
} Try / catch
try { return extractor.extractRequest(context); } catch (InvalidCibaRequestException e) { if (e.getMessage().contains("delivery mode")) { throw new InvalidGrantException("Unsupported CIBA delivery mode"); } throw e; } Prevention
- Only use 'poll' or 'ping' as backchannelTokenDeliveryMode values
- Use push mode only via the dedicated push delivery flow, not token-endpoint polling
- Validate service definitions against the OidcBackchannelTokenDeliveryModes enum before saving
When it happens
Trigger: registeredService.getBackchannelTokenDeliveryMode() parses (case-insensitively) to a mode other than POLL or PING — e.g. PUSH or a typo — while servicing a CIBA token request.
Common situations: Admin configured delivery mode 'push'; typo like 'pol' would actually fail earlier at valueOf with IllegalArgumentException; client expects push but token endpoint only serves poll/ping grants.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Registered OpenID Connect relying party does not support…
- Backchannel token delivery mode cannot grant access tokens
- Unable to use 'none' for the user-info signing algorithm
- Unable to use 'none' as user-info encryption algorithm
- Service with client id is configured to encrypt tokens, yet…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/fcd8feb92eee4ffe.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/ciba/AccessTokenCibaGrantRequestExtractor.java:72
val decodedId = cibaFactory.decodeId(authRequestId);
val cibaRequest = configurationContext.getTicketRegistry().getTicket(decodedId, OidcCibaRequest.class);
val audit = AuditableContext.builder()
.service(service)
.registeredService(registeredService)
.authentication(cibaRequest.getAuthentication())
.build();
val accessResult = configurationContext.getRegisteredServiceAccessStrategyEnforcer().execute(audit);
accessResult.throwExceptionIfNeeded();
if (!registeredService.getSupportedGrantTypes().contains(getGrantType().getType())
|| StringUtils.isBlank(registeredService.getBackchannelClientNotificationEndpoint())
|| StringUtils.isBlank(registeredService.getBackchannelTokenDeliveryMode())) {
throw new InvalidCibaRequestException("Registered OpenID Connect relying party does not support backchannel authentication requests");
}
val deliveryMode = OidcBackchannelTokenDeliveryModes.valueOf(registeredService.getBackchannelTokenDeliveryMode().toUpperCase(Locale.ENGLISH));
if (deliveryMode != OidcBackchannelTokenDeliveryModes.POLL && deliveryMode != OidcBackchannelTokenDeliveryModes.PING) {
throw new InvalidCibaRequestException("Backchannel token delivery mode cannot grant access tokens");
}
if (!cibaRequest.isReady()) {
throw new InvalidCibaRequestException("CIBA request %s is not ready to grant access tokens".formatted(authRequestId));
}
return AccessTokenRequestContext.builder()
.service(service)
.authentication(cibaRequest.getAuthentication())
.registeredService(registeredService)
.responseType(getResponseType())
.grantType(getGrantType())
.scopes(cibaRequest.getScopes())
.userProfile(profile)
.clientId(registeredService.getClientId())
.generateRefreshToken(registeredService.isGenerateRefreshToken())
.build();
}View on GitHub (pinned to e7288fc434)