{"record":{"id":"f2b339238a88f6e7","repo":"apereo/cas","slug":"no-valid-json-web-keys-used-for-encryption-can-be","errorCode":null,"errorMessage":"No valid JSON web keys used for encryption can be found","messagePattern":"No valid JSON web keys used for encryption can be found","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":285,"sourceCode":"     * @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":267,"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#L267-L291","documentation":"This warning is logged by OidcJsonWebKeyStoreUtils.fetchJsonWebKeySetForEncryption when a JWKS entry exists in the encryption keystore cache, but every contained key fails the key.getKey() != null filter — i.e. the JsonWebKey entries carry no usable Key material. The method returns Optional.empty() so no encryption key set is produced.","triggerScenarios":"Calling fetchJsonWebKeySetForEncryption with a cached JsonWebKeySet whose parsed keys are PublicJsonWebKey instances without a resolvable java.security.Key (e.g. JWKS JSON missing required parameters like 'n'/'e' for RSA or 'x'/'y' for EC, or oct keys missing 'k'), so jose4j constructs JWKs with null Key objects.","commonSituations":"Hand-edited or truncated JWKS files published by the relying party; JWKS JSON that parses as valid JSON but with malformed/missing key parameters; keys serialized without key material (public-only placeholders); encoding errors in base64url parameters.","solutions":["Validate the JWKS JSON contains complete key parameters for each key type (n+e for RSA, x+y+crv for EC, k for oct) and fix or regenerate it","Use jose4j or a JWKS validator to parse the JWKS and confirm each key yields non-null getKey() before publishing it","Re-export the keys from the original keystore (e.g. JWK from KeyStore conversion) instead of hand-authoring the JSON","If the cached entry is stale/broken, invalidate the registered-service JWKS cache and reload from a corrected source"],"exampleFix":"// before: incomplete RSA enc key in JWKS\n{\"keys\":[{\"kty\":\"RSA\",\"use\":\"enc\",\"kid\":\"rp-enc-1\"}]}\n// after: include full public key material\n{\"keys\":[{\"kty\":\"RSA\",\"use\":\"enc\",\"kid\":\"rp-enc-1\",\"n\":\"0vx7...\",\"e\":\"AQAB\"}]}","handlingStrategy":"validation","validationCode":"// Validate the JWKS fully parses into keys with real key material\nJsonWebKeySet jwks = new JsonWebKeySet(jwksJson);\nList<JsonWebKey> usable = jwks.getJsonWebKeys().stream()\n    .filter(k -> k.getKey() != null).toList();\nif (usable.isEmpty()) {\n    throw new IllegalStateException(\"JWKS parses but no keys carry key material \"\n        + \"(check n/e for RSA, x/y/crv for EC, k for oct)\");\n}","typeGuard":"static boolean allKeysHaveMaterial(JsonWebKeySet jwks) {\n    return !jwks.getJsonWebKeys().isEmpty()\n        && jwks.getJsonWebKeys().stream().allMatch(k -> k.getKey() != null);\n}","tryCatchPattern":"try {\n    Optional<JsonWebKeySet> keys =\n        OidcJsonWebKeyStoreUtils.fetchJsonWebKeySetForEncryption(service, cipherExecutor);\n    if (keys.isEmpty()) {\n        LOG.warn(\"Cached enc JWKS has no usable key material for {}\", service.getClientId());\n    }\n} catch (Exception e) {\n    LOG.error(\"Failed to build encryption key set\", e);\n}","preventionTips":["Never hand-author JWKS JSON; export keys programmatically (e.g. jose4j PublicJsonWebKey.toJson) so all parameters are present","Run a JWKS lint/parse step in CI before publishing keys","Diff published JWKS against the source keystore after edits","Invalidate the JWKS cache after replacing a malformed key so the fixed version is reloaded"],"tags":["oidc","jwks","encryption","invalid-key-material"],"backgroundTag":"schema-validation-failed","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"}