{"record":{"id":"d44b0a42c5f51e22","repo":"spring-projects/spring-security","slug":"unsupported-key-selector-type-jwskeyselector-get","errorCode":null,"errorMessage":"Unsupported key selector type + jwsKeySelector.getClass()","messagePattern":"Unsupported key selector type \\+ jwsKeySelector\\.getClass\\(\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java","lineNumber":532,"sourceCode":"\t\t\t\t.map((processor) -> Tuples.of(processor, getExpectedJwsAlgorithms(processor.getJWSKeySelector())))\n\t\t\t\t.cache((processor) -> FOREVER, (ex) -> Duration.ZERO, () -> Duration.ZERO);\n\t\t\treturn (jwt) -> {\n\t\t\t\treturn jwtProcessorMono.flatMap((tuple) -> {\n\t\t\t\t\tConfigurableJWTProcessor<JWKSecurityContext> processor = tuple.getT1();\n\t\t\t\t\tFunction<JWSAlgorithm, Boolean> expectedJwsAlgorithms = tuple.getT2();\n\t\t\t\t\tJWKSelector selector = createSelector(expectedJwsAlgorithms, jwt.getHeader());\n\t\t\t\t\treturn source.get(selector)\n\t\t\t\t\t\t.onErrorMap((ex) -> new IllegalStateException(\"Could not obtain the keys\", ex))\n\t\t\t\t\t\t.map((jwkList) -> createClaimsSet(processor, jwt, new JWKSecurityContext(jwkList)));\n\t\t\t\t});\n\t\t\t};\n\t\t}\n\n\t\tprivate Function<JWSAlgorithm, Boolean> getExpectedJwsAlgorithms(JWSKeySelector<?> jwsKeySelector) {\n\t\t\tif (jwsKeySelector instanceof JWSVerificationKeySelector) {\n\t\t\t\treturn ((JWSVerificationKeySelector<?>) jwsKeySelector)::isAllowed;\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(\"Unsupported key selector type \" + jwsKeySelector.getClass());\n\t\t}\n\n\t\tprivate JWKSelector createSelector(Function<JWSAlgorithm, Boolean> expectedJwsAlgorithms, Header header) {\n\t\t\tJWSHeader jwsHeader = (JWSHeader) header;\n\t\t\tif (!expectedJwsAlgorithms.apply(jwsHeader.getAlgorithm())) {\n\t\t\t\tthrow new BadJwtException(\"Unsupported algorithm of \" + header.getAlgorithm());\n\t\t\t}\n\t\t\treturn new JWKSelector(JWKMatcher.forJWSHeader(jwsHeader));\n\t\t}\n\n\t}\n\n\t/**\n\t * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a public\n\t * key.\n\t *\n\t * @since 5.2\n\t */","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java#L514-L550","documentation":"getExpectedJwsAlgorithms (inside NimbusReactiveJwtDecoder's builder/processor wiring) only understands JWSVerificationKeySelector; when the configured JWSKeySelector is any other Nimbus type it throws IllegalArgumentException 'Unsupported key selector type <class>'. This is an internal invariant: Spring Security's decoder expects the key selector it (or you) configured to be a JWSVerificationKeySelector so it can derive the allowed JWS algorithms.","triggerScenarios":"Building the decoder so that the underlying ConfigurableJWTProcessor's JWSKeySelector is not a JWSVerificationKeySelector — e.g. passing a custom JWSKeySelector (JWEDecryptionKeySelector, implicit/ federated selectors, or a custom implementation) into the Nimbus configuration used by jwtProcessorMono, then the decoder tries to compute expected algorithms for JWK selection.","commonSituations":"Customizing Nimbus internals by supplying a bespoke JWSKeySelector; library/version change where Nimbus returns a wrapped selector type; copying configuration code that sets a key selector Spring Security does not recognize.","solutions":["Use Spring Security's supported customization points (withJwkSetUri, withPublicKey, withSecretKey, setJwsAlgorithms) instead of a custom JWSKeySelector","If a custom selector is required, extend or wrap JWSVerificationKeySelector so the instanceof check passes","Downstream of this error, only provide algorithms via setJwsAlgorithms on the builder rather than replacing the selector"],"exampleFix":"// before\nprocessor.setJWSKeySelector(new MyCustomJWSKeySelector<>()); // throws in getExpectedJwsAlgorithms\n// after\nNimbusReactiveJwtDecoder decoder = NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri)\n    .jwsAlgorithms(algs -> algs.addAll(List.of(SignatureAlgorithm.RS256, SignatureAlgorithm.ES256)))\n    .build();","handlingStrategy":"type-guard","validationCode":"// before building, assert the selector type the decoder supports\nif (!(jwsKeySelector instanceof JWSVerificationKeySelector)) {\n  throw new IllegalStateException(\"Configure algorithms via setJwsAlgorithms, not a custom JWSKeySelector\");\n}","typeGuard":"static boolean isSupportedKeySelector(JWSKeySelector<?> sel) {\n  return sel instanceof JWSVerificationKeySelector;\n}","tryCatchPattern":"try {\n  NimbusReactiveJwtDecoder decoder = builder.build();\n} catch (IllegalArgumentException ex) {\n  if (ex.getMessage().startsWith(\"Unsupported key selector type\")) {\n    throw new ConfigurationException(\"Use builder.setJwsAlgorithms instead of a custom JWSKeySelector\");\n  }\n  throw ex;\n}","preventionTips":["Configure allowed algorithms via the builder's setJwsAlgorithms, never by replacing the Nimbus JWSKeySelector","If Nimbus customization is unavoidable, extend JWSVerificationKeySelector rather than implementing JWSKeySelector from scratch","Pin Nimbus JOSE+JWT versions compatible with your Spring Security version","Write a startup smoke test that decodes a sample token to surface configuration errors early"],"tags":["jwt","configuration","unsupported-operation","spring-security"],"backgroundTag":"unsupported-operation","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"}