{"record":{"id":"a9d9277a178563d2","repo":"apereo/cas","slug":"service-with-client-id-is-configured-to","errorCode":null,"errorMessage":"Service [{}] with client id [{}] is configured to encrypt tokens, yet no JSON web key is available","messagePattern":"Service \\[(.+?)\\] with client id \\[(.+?)\\] is configured to encrypt tokens, yet no JSON web key is available","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/jwks/OidcJsonWebKeyStoreUtils.java","lineNumber":276,"sourceCode":"        }\n        LOGGER.warn(\"No [{}] key could be found for issuer [{}]\", OidcJsonWebKeyUsage.SIGNING, issuer);\n        return Optional.empty();\n    }\n\n    /**\n     * Fetch json web key set for encryption.\n     *\n     * @param registeredService the registered service\n     * @param cipherExecutor    the cipher executor\n     * @return the optional\n     */\n    public static Optional<JsonWebKeySet> fetchJsonWebKeySetForEncryption(final RegisteredService registeredService,\n                                                                          final OidcRegisteredServiceJwtCipherExecutor cipherExecutor) {\n        val oidcRegisteredService = (OidcRegisteredService) registeredService;\n        val jwks = Objects.requireNonNull(cipherExecutor.getRegisteredServiceJsonWebKeystoreCache().get(\n            new OidcJsonWebKeyCacheKey(oidcRegisteredService, OidcJsonWebKeyUsage.ENCRYPTION)));\n        if (jwks.isEmpty()) {\n            LOGGER.warn(\"Service [{}] with client id [{}] is configured to encrypt tokens, yet no JSON web key is available\",\n                oidcRegisteredService.getServiceId(), oidcRegisteredService.getClientId());\n            return Optional.empty();\n        }\n        val jsonWebKey = jwks.get();\n        LOGGER.debug(\"Found JSON web key to encrypt the token: [{}]\", jsonWebKey);\n\n        val keys = jsonWebKey.getJsonWebKeys().stream().filter(key -> key.getKey() != null).toList();\n        if (keys.isEmpty()) {\n            LOGGER.warn(\"No valid JSON web keys used for encryption can be found\");\n            return Optional.empty();\n        }\n        return Optional.of(new JsonWebKeySet(keys));\n    }\n}\n","sourceCodeStart":258,"sourceCodeEnd":291,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/jwks/OidcJsonWebKeyStoreUtils.java#L258-L291","documentation":"This warning is logged by OidcJsonWebKeySetUtils.fetchJsonWebKeySetForEncryption (OidcJsonWebKeyStoreUtils.java:276) when a service is flagged for token encryption but the registered-service JWKS cache contains no entry for ENCRYPTION usage; the method returns Optional.empty() so the token cannot be encrypted with the client's key.","triggerScenarios":"fetchJsonWebKeySetForEncryption is called for an OidcRegisteredService that requires encrypted ID tokens/tokens, but cipherExecutor.getRegisteredServiceJsonWebKeystoreCache().get(new OidcJsonWebKeyCacheKey(service, ENCRYPTION)) returns an empty Optional — i.e. no encryption key was ever loaded/created for that service's JWKS.","commonSituations":"Service has token encryption enabled but its jwks URL/keystore contains only signing keys (no use=enc keys); the remote JWKS endpoint is unreachable so the cache never populated; the service's jwks property is blank or points to a stale file; after cache invalidation the encryption keys were not re-fetched.","solutions":["Ensure the service's JWKS contains keys with use=enc (encryption) and that the jwks property on the OidcRegisteredService points to a reachable, valid JWKS resource","If the service should not encrypt tokens, disable the token-encryption setting on the OidcRegisteredService","Verify the remote JWKS endpoint (e.g. the client's jwks_uri) is up and returns 2xx; fix networking/auth and reload the service registry","Clear and rebuild the registered-service JWKS cache so encryption keys are re-fetched after fixing the source"],"exampleFix":"// before: service flags encryption but only signing keys exist\n\"@class\":\"org.apereo.cas.services.OidcRegisteredService\",\n\"jwks\":\"https://rp.example.com/jwks.json\" // keys all have use=sign\n// after: publish an enc key in the RP JWKS (or disable encryption)\n// JWKS at https://rp.example.com/jwks.json now includes:\n{\"kty\":\"RSA\",\"use\":\"enc\",\"kid\":\"rp-enc-1\",\"n\":\"...\",\"e\":\"AQAB\"}","handlingStrategy":"validation","validationCode":"// Before enabling token encryption for a service, verify enc keys exist in its JWKS\nJsonWebKeySet jwks = new JsonWebKeySet(fetchJwks(service.getJwks()));\nboolean hasEncKey = jwks.getJsonWebKeys().stream()\n    .anyMatch(k -> \"enc\".equals(k.getUse()) && k.getKey() != null);\nif (!hasEncKey) {\n    throw new IllegalStateException(\"Service \" + service.getClientId()\n        + \" requires encryption but its JWKS has no use=enc key\");\n}","typeGuard":"static boolean serviceHasEncryptionKeys(OidcRegisteredService service, JsonWebKeySet jwks) {\n    return jwks.getJsonWebKeys().stream()\n        .anyMatch(k -> OidcJsonWebKeyUsage.ENCRYPTION.is(k) && k.getKey() != null);\n}","tryCatchPattern":"try {\n    Optional<JsonWebKeySet> keys =\n        OidcJsonWebKeyStoreUtils.fetchJsonWebKeySetForEncryption(service, cipherExecutor);\n    if (keys.isEmpty()) {\n        LOG.warn(\"Skipping token encryption for client {} - no enc JWKS\", service.getClientId());\n    }\n} catch (Exception e) {\n    LOG.error(\"Encryption JWKS fetch failed for {}\", service.getClientId(), e);\n}","preventionTips":["Only enable token encryption on an OidcRegisteredService after its JWKS publishes an enc key","Monitor the client's jwks_uri availability; a dead endpoint empties the cache","Reload the service registry after fixing JWKS sources so caches repopulate","Test encrypted-token issuance in a staging environment before enabling in production"],"tags":["oidc","jwks","encryption","cache-miss"],"backgroundTag":"record-not-found","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}