The ConfigurableJWTProcessor.setJWSKeySelector(JWSKeySelector) is unable to update the reference used by NimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder.processor(). The processor holds a reference to the default JWSKeySelector created within NimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder.jwsKeySelector() via a method reference within JwkSetUriReactiveJwtDecoderBuilder.getExpectedJwsAlgorithms() before the ConfigurableJWTProcessorsetJWSKeySelector(JWSKeySelector) is executed.
The following unit test will show that the processor is executing the wrong JWSVerificationKeySelector.isAllowed(JWSAlgorithm) reference.
@ExtendWith(MockitoExtension.class)
class NimbusReactiveJwtDecoderTest {
@Mock private WebClient webClient;
@Mock private RequestHeadersUriSpec<?> requestHeadersUriSpec;
@Mock private ResponseSpec responseSpec;
@Test
void customizeJWSKeySelector() throws Exception {
var jwkSet = new JWKSet(
new RSAKeyGenerator(RSAKeyGenerator.MIN_KEY_SIZE_BITS)
.algorithm(JWSAlgorithm.RS512)
.keyID(UUID.randomUUID().toString())
.keyUse(KeyUse.SIGNATURE)
.generate());
var jwkSource = new ImmutableJWKSet<>(jwkSet);
var jwt = new NimbusJwtEncoder(jwkSource).encode(
JwtEncoderParameters.from(JwsHeader.with(SignatureAlgorithm.RS512).build(),
JwtClaimsSet.builder().issuer("issuer").build()));
// stub WebClient response for ReactiveRemoteJWKSource
Mockito.doReturn(requestHeadersUriSpec).when(webClient).get();
Mockito.doReturn(requestHeadersUriSpec).when(requestHeadersUriSpec).uri(Mockito.anyString());
Mockito.when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec);
Mockito.when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(jwkSet.toString()));
var decoder = NimbusReactiveJwtDecoder
.withJwkSetUri("http://localhost/oauth2/jwks") // use NimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder
.webClient(webClient) // stub remote call
.jwtProcessorCustomizer(processor -> {
// this reference will not be used by the "Function<JWSAlgorithm, Boolean> expectedJwsAlgorithms" within JwkSetUriReactiveJwtDecoderBuilder.processor()
var jwsKeySelector = new JWSVerificationKeySelector<>(Set.of(JWSAlgorithm.RS512), jwkSource);
// the JwkSetUriReactiveJwtDecoderBuilder.processor() still holds a reference to the JWSVerificationKeySelector instantiated
// within JwkSetUriReactiveJwtDecoderBuilder.jwsKeySelector(), via the method reference created by JwkSetUriReactiveJwtDecoderBuilder.getExpectedJwsAlgorithms(), held before the customizer is executed.
processor.setJWSKeySelector((JWSVerificationKeySelector) jwsKeySelector);
})
.build();
// execute the processor
decoder.decode(jwt.getTokenValue())
.block();
}
}
The
ConfigurableJWTProcessor.setJWSKeySelector(JWSKeySelector)is unable to update the reference used byNimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder.processor(). The processor holds a reference to the defaultJWSKeySelectorcreated withinNimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder.jwsKeySelector()via a method reference withinJwkSetUriReactiveJwtDecoderBuilder.getExpectedJwsAlgorithms()before theConfigurableJWTProcessorsetJWSKeySelector(JWSKeySelector)is executed.The following unit test will show that the processor is executing the wrong
JWSVerificationKeySelector.isAllowed(JWSAlgorithm)reference.