{"record":{"id":"80aebcee16638962","repo":"apache/pulsar","slug":"malformed-jwks-returned-by","errorCode":null,"errorMessage":"Malformed JWKS returned by: ","messagePattern":"Malformed JWKS returned by: ","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-auth-oidc/src/main/java/org/apache/pulsar/broker/authentication/oidc/JwksCache.java","lineNumber":243,"sourceCode":"\n    /**\n     * The JWK Set is stored in the \"keys\" key see https://www.rfc-editor.org/rfc/rfc7517#section-5.1.\n     *\n     * @param jwksUri - the URI used to retrieve the JWKS\n     * @param jwks - the JWKS to convert\n     * @return a list of {@link Jwk}\n     */\n    private List<Jwk> convertToJwks(String jwksUri, Map<String, Object> jwks) throws AuthenticationException {\n        try {\n            @SuppressWarnings(\"unchecked\")\n            List<Map<String, Object>> jwkList = (List<Map<String, Object>>) jwks.get(\"keys\");\n            final List<Jwk> result = new ArrayList<>();\n            for (Map<String, Object> jwk : jwkList) {\n                result.add(Jwk.fromValues(jwk));\n            }\n            return result;\n        } catch (ClassCastException e) {\n            throw new AuthenticationException(\"Malformed JWKS returned by: \" + jwksUri);\n        }\n    }\n}\n","sourceCodeStart":225,"sourceCodeEnd":247,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-auth-oidc/src/main/java/org/apache/pulsar/broker/authentication/oidc/JwksCache.java#L225-L247","documentation":"JwksCache.convertToJwks() expects the fetched JWKS document to be a JSON object with a \"keys\" member holding an array of key objects (RFC 7517 section 5.1). If casting the parsed document's \"keys\" value to List<Map<String,Object>> throws ClassCastException — e.g. \"keys\" is missing (null), not a list, or contains non-map entries — the method rethrows it as AuthenticationException(\"Malformed JWKS returned by: <uri>\").","triggerScenarios":"The endpoint at jwksUri returns JSON that is not a JWK Set: an error page (HTML) that still parses as generic JSON, a JSON object without a \"keys\" array, \"keys\" being a single object instead of an array, or an array of strings/numbers instead of key objects; in the Kubernetes path, the API server's .well-known/openid-configuration keyset returns an unexpected shape.","commonSituations":"Misconfigured jwks_uri pointing to the issuer's .well-known/openid-configuration document or a login page instead of the actual JWKS endpoint; a proxy/gateway intercepting the JWKS request and returning an error JSON body; a non-standard IdP or mocked test server serving a hand-written JWKS with a wrong structure.","solutions":["Fetch the configured jwksUri with curl and verify it is a JWK Set: {\"keys\":[{...}]} with each key an object containing kty etc.","Correct the jwks_uri configuration — it must point to the JWKS endpoint, not the discovery document or an HTML page.","Check for proxies/ingress returning error bodies with 200 status, and bypass or fix them.","If the IdP is non-standard, ensure its keyset endpoint conforms to RFC 7517 before connecting it."],"exampleFix":"// before (wrong endpoint configured)\nownedTenant=\"https://idp.example.com/.well-known/openid-configuration\"\n// after (actual JWKS endpoint)\njwksUri=https://idp.example.com/.well-known/jwks.json","handlingStrategy":"validation","validationCode":"curl -fsSL \"$JWKS_URI\" | jq -e '(.keys | type) == \"array\" and (.keys | length) > 0 and (.keys[0] | type) == \"object\"' >/dev/null \\\n  && echo OK || echo \"Not a valid JWK Set\"","typeGuard":null,"tryCatchPattern":"try {\n    List<Jwk> jwks = fetchAndConvert(jwksUri);\n} catch (AuthenticationException e) {\n    if (e.getMessage().startsWith(\"Malformed JWKS returned by\")) {\n        // verify endpoint config / check for proxy-injected error bodies\n    }\n}","preventionTips":["Point the JWKS configuration at the real JWKS endpoint (…/.well-known/jwks.json / jwks_uri from discovery), never the discovery document itself.","Validate the JWKS endpoint's JSON shape after any IdP or proxy change.","Watch for gateways that return HTML/JSON errors with HTTP 200."],"tags":["jwks","oidc","json","validation","authentication"],"backgroundTag":"malformed-jwks-response","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}