apereo/cas · error · IllegalArgumentException
Service with client id is configured to encrypt tokens, yet…
Error message
Service %s with client id %s is configured to encrypt tokens, yet no JSON web key is available to handle encryption
What it means
BaseOidcJsonWebKeyTokenSigningAndEncryptionService.getJsonWebKeyForEncryption throws this when a registered OIDC client is configured to receive encrypted tokens but no usable JSON web key can be resolved for the encryption step. If id-token encryption is optional (oidcService.isIdTokenEncryptionOptional()) CAS only logs and returns null; otherwise it fails hard.
Solutions
- Publish a valid JWKS at the client's registered jwks_uri containing a current encryption key
- Enable cas.authn.oidc.core.id-token-encryption-optional=true so encryption is skipped (logged) instead of failing
- Check the CAS JWK keystore rotation state so at least one key is in the CURRENT state
- Verify the JWKS URI is reachable from the CAS server (network/TLS/firewall)
Example fix
// before (cas.properties) cas.authn.oidc.core.id-token-encryption-optional=false // after (make encryption best-effort) cas.authn.oidc.core.id-token-encryption-optional=true // or fix the client's JWKS so a current key exists
Defensive patterns
Strategy: try-catch
Validate before calling
var jwks = fetchJwks(client.getJwksUri());
if (jwks == null || jwks.getJsonWebKeys().stream().noneMatch(k -> "current".equals(stateOf(k)))) {
throw new IllegalStateException("Client " + client.getClientId() + " has no current encryption key in JWKS");
} Try / catch
try { return encryptionService.encrypt(token, service); } catch (IllegalArgumentException e) { if (e.getMessage().contains("no JSON web key")) { log.warn("Skipping encryption for {}", service.getClientId()); return unencrypted(token); } throw e; } Prevention
- Verify each encryption-enabled client publishes a reachable JWKS with a current key
- Monitor JWKS fetch failures in CAS logs
- Set id-token-encryption-optional=true if encryption is best-effort
When it happens
Trigger: encryptionKey() runs for a service with encryption enabled, but the client's JWKS is absent/unfetchable, contains no keys in the 'current' lifecycle state, or no key matches the required use/algorithm; and cas.authn.oidc.core.id-token-encryption-optional=false.
Common situations: Client did not publish a JWKS at its registered jwks_uri; all keys in the rotation store are expired/retired; JWKS fetch fails (network, TLS); server upgraded with token encryption now mandatory.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Unable to use 'none' as user-info encryption algorithm
- Unable to use 'none' as ID token encryption algorithm
- Service [ ] with client id [ ] is configured to encrypt…
- No valid JSON web keys used for encryption can be found
- JWKS cannot contain expressions
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/450e690530b1a0c3.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/BaseOidcJsonWebKeyTokenSigningAndEncryptionService.java:137
.flatMap(Optional::stream)
.findFirst();
LOGGER.debug("Located key [{}] for service [{}]", finalKey, serviceResult);
return finalKey.orElseGet(() -> (PublicJsonWebKey) jsonWebKeys.getFirst());
}
protected @Nullable PublicJsonWebKey getJsonWebKeyForEncryption(final OAuthRegisteredService registeredService) {
LOGGER.debug("Service [{}] is set to encrypt tokens", registeredService);
val oidcService = (OidcRegisteredService) registeredService;
val jwks = serviceJsonWebKeystoreCache.get(new OidcJsonWebKeyCacheKey(registeredService, OidcJsonWebKeyUsage.ENCRYPTION));
if (jwks.isEmpty()) {
val message = "Service %s with client id %s is configured to encrypt tokens, yet no JSON web key is available to handle encryption"
.formatted(registeredService.getServiceId(), registeredService.getClientId());
if (oidcService.isIdTokenEncryptionOptional()) {
LOGGER.info(message);
return null;
}
throw new IllegalArgumentException(message);
}
val jsonWebKey = jwks.get()
.getJsonWebKeys()
.stream()
.filter(key -> OidcJsonWebKeystoreRotationService.JsonWebKeyLifecycleStates.getJsonWebKeyState(key).isCurrent())
.min(Comparator.comparing(JsonWebKey::getKeyId))
.orElseThrow(() -> new IllegalArgumentException("Cannot locate current JSON web key for encryption"));
LOGGER.debug("Found JSON web key to encrypt the token: [{}]", jsonWebKey);
Objects.requireNonNull(jsonWebKey.getKey(), "JSON web key used to encrypt the token has no associated public key");
return (PublicJsonWebKey) jsonWebKey;
}
}
View on GitHub (pinned to e7288fc434)