{"record":{"id":"2514e1c04c1db7fe","repo":"spring-projects/spring-security","slug":"invalid-key","errorCode":"invalid_key","errorMessage":"Failed to resolve JWK signing key for client registration '${registrationId}'.","messagePattern":"Failed to resolve JWK signing key for client registration '(.+?)'\\.","errorType":"error_code","errorClass":"OAuth2AuthorizationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusJwtClientAuthenticationParametersConverter.java","lineNumber":124,"sourceCode":"\n\t@Override\n\tpublic @Nullable MultiValueMap<String, String> convert(T authorizationGrantRequest) {\n\t\tAssert.notNull(authorizationGrantRequest, \"authorizationGrantRequest cannot be null\");\n\n\t\tClientRegistration clientRegistration = authorizationGrantRequest.getClientRegistration();\n\t\tif (!ClientAuthenticationMethod.PRIVATE_KEY_JWT.equals(clientRegistration.getClientAuthenticationMethod())\n\t\t\t\t&& !ClientAuthenticationMethod.CLIENT_SECRET_JWT\n\t\t\t\t\t.equals(clientRegistration.getClientAuthenticationMethod())) {\n\t\t\treturn null;\n\t\t}\n\n\t\tJWK jwk = this.jwkResolver.apply(clientRegistration);\n\t\tif (jwk == null) {\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(INVALID_KEY_ERROR_CODE,\n\t\t\t\t\t\"Failed to resolve JWK signing key for client registration '\"\n\t\t\t\t\t\t\t+ clientRegistration.getRegistrationId() + \"'.\",\n\t\t\t\t\tnull);\n\t\t\tthrow new OAuth2AuthorizationException(oauth2Error);\n\t\t}\n\n\t\tJwsAlgorithm jwsAlgorithm = resolveAlgorithm(jwk);\n\t\tif (jwsAlgorithm == null) {\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(INVALID_ALGORITHM_ERROR_CODE,\n\t\t\t\t\t\"Unable to resolve JWS (signing) algorithm from JWK associated to client registration '\"\n\t\t\t\t\t\t\t+ clientRegistration.getRegistrationId() + \"'.\",\n\t\t\t\t\tnull);\n\t\t\tthrow new OAuth2AuthorizationException(oauth2Error);\n\t\t}\n\n\t\tJwsHeader.Builder headersBuilder = JwsHeader.with(jwsAlgorithm);\n\n\t\tInstant issuedAt = Instant.now();\n\t\tInstant expiresAt = issuedAt.plus(Duration.ofSeconds(60));\n\n\t\t// @formatter:off\n\t\tJwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder()","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusJwtClientAuthenticationParametersConverter.java#L106-L142","documentation":"For clients that authenticate with a signed JWT (private_key_jwt / client_secret_jwt), NimbusJwtClientAuthenticationParametersConverter asks the configured jwkResolver for a JWK. When the resolver returns null, Spring Security cannot sign the client assertion and throws invalid_key. This means no signing key was found for the given client registration.","triggerScenarios":"Thrown in convert() when this.jwkResolver.apply(clientRegistration) returns null — typically because the JWKSet/source registered for that registrationId has no key, or the resolver's predicate filters it out.","commonSituations":"Keystore or JWK Set source not loaded/empty, wrong registrationId mapped in the resolver, key type mismatch (resolver expects RSA but keystore holds EC), or developer forgot to configure a jwkResolver at all while using private_key_jwt.","solutions":["Ensure a JWK resolver is configured: NimbusJwtClientAuthenticationParametersConverter<JwkResolvers...> with a resolver returning a JWK for the registrationId.","Verify the keystore/JWK Set actually contains a key matching the registrationId and type (RSA for RS256/PS256, EC for ES256).","Check the resolver's filter logic (algorithm/key-use constraints) isn't discarding the only available key.","Confirm the registration actually requires client authentication via JWT; if not, use client_secret_basic instead."],"exampleFix":"// before: resolver returns null for unknown registrations\nJWK jwk = jwkSet.getKeys().stream().filter(k -> matches(k)).findFirst().orElse(null);\n// after: fail fast at startup if the key is absent\nJWK jwk = Objects.requireNonNull(resolveJwk(registrationId), \"No JWK for \" + registrationId);","handlingStrategy":"validation","validationCode":"// startup check\nJWK jwk = jwkResolver.apply(clientRegistration);\nif (jwk == null) {\n    throw new IllegalStateException(\n        \"No signing JWK available for registration \" + clientRegistration.getRegistrationId()\n        + \"; check keystore/JWK Set and resolver filter\");\n}","typeGuard":"boolean hasSigningJwk(ClientRegistration reg) {\n    JWK jwk = jwkResolver.apply(reg);\n    return jwk != null && \"sig\".equals(jwk.getKeyUse() != null ? jwk.getKeyUse().getValue() : null);\n}","tryCatchPattern":"catch (OAuth2AuthorizationException ex) { if (\"invalid_key\".equals(ex.getError().getErrorCode())) { log.error(\"Missing signing JWK for registration; failing fast\"); throw new ConfigurationException(ex); } throw ex; }","preventionTips":["Fail at startup if the keystore/JWK Set has no key for each private_key_jwt registration.","Name/lookup JWKs by registrationId consistently and test the resolver in unit tests.","Keep kty/use/alg metadata populated on exported JWKs.","Mount/decrypt keystores before the application accepts traffic."],"tags":["oauth2","jwk","jwt","client-authentication","spring-security"],"backgroundTag":"missing-credentials","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}