Skip to content

Commit 3ddc494

Browse files
author
Nick Meverden
committed
Delay JWSVerificationKeySelector Construction
Updating the NimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder processor to execute the ConfigurableJWTProcessor customizations before holding a reference to the JWSKeySelector. Closes gh-12960
1 parent e251178 commit 3ddc494

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,6 +55,8 @@
5555
import com.nimbusds.jwt.proc.JWTProcessor;
5656
import reactor.core.publisher.Flux;
5757
import reactor.core.publisher.Mono;
58+
import reactor.util.function.Tuple2;
59+
import reactor.util.function.Tuples;
5860

5961
import org.springframework.core.convert.converter.Converter;
6062
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -388,15 +390,19 @@ Converter<JWT, Mono<JWTClaimsSet>> processor() {
388390
});
389391
ReactiveRemoteJWKSource source = new ReactiveRemoteJWKSource(this.jwkSetUri);
390392
source.setWebClient(this.webClient);
391-
Function<JWSAlgorithm, Boolean> expectedJwsAlgorithms = getExpectedJwsAlgorithms(jwsKeySelector);
392-
Mono<ConfigurableJWTProcessor<JWKSecurityContext>> jwtProcessorMono = this.jwtProcessorCustomizer
393+
Mono<Tuple2<ConfigurableJWTProcessor<JWKSecurityContext>, Function<JWSAlgorithm, Boolean>>> jwtProcessorMono = this.jwtProcessorCustomizer
393394
.apply(source, jwtProcessor)
395+
.map((processor) -> Tuples.of(processor, getExpectedJwsAlgorithms(processor.getJWSKeySelector())))
394396
.cache((processor) -> FOREVER, (ex) -> Duration.ZERO, () -> Duration.ZERO);
395397
return (jwt) -> {
396-
JWKSelector selector = createSelector(expectedJwsAlgorithms, jwt.getHeader());
397-
return jwtProcessorMono.flatMap((processor) -> source.get(selector)
398-
.onErrorMap((ex) -> new IllegalStateException("Could not obtain the keys", ex))
399-
.map((jwkList) -> createClaimsSet(processor, jwt, new JWKSecurityContext(jwkList))));
398+
return jwtProcessorMono.flatMap((tuple) -> {
399+
JWTProcessor<JWKSecurityContext> processor = tuple.getT1();
400+
Function<JWSAlgorithm, Boolean> expectedJwsAlgorithms = tuple.getT2();
401+
JWKSelector selector = createSelector(expectedJwsAlgorithms, jwt.getHeader());
402+
return source.get(selector)
403+
.onErrorMap((ex) -> new IllegalStateException("Could not obtain the keys", ex))
404+
.map((jwkList) -> createClaimsSet(processor, jwt, new JWKSecurityContext(jwkList)));
405+
});
400406
};
401407
}
402408

oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@
3939
import com.nimbusds.jose.JWSSigner;
4040
import com.nimbusds.jose.crypto.MACSigner;
4141
import com.nimbusds.jose.jwk.JWKSet;
42+
import com.nimbusds.jose.jwk.RSAKey;
43+
import com.nimbusds.jose.jwk.source.JWKSecurityContextJWKSet;
4244
import com.nimbusds.jose.jwk.source.JWKSource;
4345
import com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier;
4446
import com.nimbusds.jose.proc.JWKSecurityContext;
@@ -365,6 +367,20 @@ public void withJwkSetUriWhenUsingCustomTypeHeaderThenRefuseOmittedType() {
365367
// @formatter:on
366368
}
367369

370+
@Test
371+
public void withJwkSetUriWhenJwtProcessorCustomizerSetsJWSKeySelectorThenUseCustomizedJWSKeySelector()
372+
throws InvalidKeySpecException {
373+
WebClient webClient = mockJwkSetResponse(new JWKSet(new RSAKey.Builder(key()).build()).toString());
374+
// @formatter:off
375+
NimbusReactiveJwtDecoder decoder = NimbusReactiveJwtDecoder.withJwkSetUri(this.jwkSetUri)
376+
.jwsAlgorithm(SignatureAlgorithm.ES256).webClient(webClient)
377+
.jwtProcessorCustomizer((p) -> p
378+
.setJWSKeySelector(new JWSVerificationKeySelector<>(JWSAlgorithm.RS512, new JWKSecurityContextJWKSet())))
379+
.build();
380+
assertThat(decoder.decode(this.rsa512).block()).extracting(Jwt::getSubject).isEqualTo("test-subject");
381+
// @formatter:on
382+
}
383+
368384
@Test
369385
public void withPublicKeyWhenNullThenThrowsException() {
370386
// @formatter:off

0 commit comments

Comments
 (0)