Merge branch '6.5.x' into 7.0.x
This commit is contained in:
+13
-2
@@ -232,7 +232,8 @@ public final class NimbusJwtDecoder implements JwtDecoder {
|
|||||||
.getConfigurationForIssuerLocation(issuer, rest);
|
.getConfigurationForIssuerLocation(issuer, rest);
|
||||||
JwtDecoderProviderConfigurationUtils.validateIssuer(configuration, issuer);
|
JwtDecoderProviderConfigurationUtils.validateIssuer(configuration, issuer);
|
||||||
return configuration.get("jwks_uri").toString();
|
return configuration.get("jwks_uri").toString();
|
||||||
}, JwtDecoderProviderConfigurationUtils::getJWSAlgorithms);
|
}, JwtDecoderProviderConfigurationUtils::getJWSAlgorithms)
|
||||||
|
.validator(JwtValidators.createDefaultWithIssuer(issuer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,6 +302,8 @@ public final class NimbusJwtDecoder implements JwtDecoder {
|
|||||||
|
|
||||||
private Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer;
|
private Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer;
|
||||||
|
|
||||||
|
private OAuth2TokenValidator<Jwt> validator = JwtValidators.createDefault();
|
||||||
|
|
||||||
private JwkSetUriJwtDecoderBuilder(String jwkSetUri) {
|
private JwkSetUriJwtDecoderBuilder(String jwkSetUri) {
|
||||||
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
|
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
|
||||||
this.jwkSetUri = (rest) -> jwkSetUri;
|
this.jwkSetUri = (rest) -> jwkSetUri;
|
||||||
@@ -441,6 +444,12 @@ public final class NimbusJwtDecoder implements JwtDecoder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JwkSetUriJwtDecoderBuilder validator(OAuth2TokenValidator<Jwt> validator) {
|
||||||
|
Assert.notNull(validator, "validator cannot be null");
|
||||||
|
this.validator = validator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
JWSKeySelector<SecurityContext> jwsKeySelector(JWKSource<SecurityContext> jwkSource) {
|
JWSKeySelector<SecurityContext> jwsKeySelector(JWKSource<SecurityContext> jwkSource) {
|
||||||
if (this.signatureAlgorithms.isEmpty()) {
|
if (this.signatureAlgorithms.isEmpty()) {
|
||||||
return new JWSVerificationKeySelector<>(this.defaultAlgorithms.apply(jwkSource), jwkSource);
|
return new JWSVerificationKeySelector<>(this.defaultAlgorithms.apply(jwkSource), jwkSource);
|
||||||
@@ -479,7 +488,9 @@ public final class NimbusJwtDecoder implements JwtDecoder {
|
|||||||
* @return the configured {@link NimbusJwtDecoder}
|
* @return the configured {@link NimbusJwtDecoder}
|
||||||
*/
|
*/
|
||||||
public NimbusJwtDecoder build() {
|
public NimbusJwtDecoder build() {
|
||||||
return new NimbusJwtDecoder(processor());
|
NimbusJwtDecoder decoder = new NimbusJwtDecoder(processor());
|
||||||
|
decoder.setJwtValidator(this.validator);
|
||||||
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SpringJWKSource<C extends SecurityContext> implements JWKSetSource<C> {
|
private static final class SpringJWKSource<C extends SecurityContext> implements JWKSetSource<C> {
|
||||||
|
|||||||
+12
-2
@@ -241,7 +241,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|||||||
}
|
}
|
||||||
return Mono.just(configuration.get("jwks_uri").toString());
|
return Mono.just(configuration.get("jwks_uri").toString());
|
||||||
}),
|
}),
|
||||||
ReactiveJwtDecoderProviderConfigurationUtils::getJWSAlgorithms);
|
ReactiveJwtDecoderProviderConfigurationUtils::getJWSAlgorithms)
|
||||||
|
.validator(JwtValidators.createDefaultWithIssuer(issuer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -332,6 +333,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|||||||
|
|
||||||
private BiFunction<ReactiveRemoteJWKSource, ConfigurableJWTProcessor<JWKSecurityContext>, Mono<ConfigurableJWTProcessor<JWKSecurityContext>>> jwtProcessorCustomizer;
|
private BiFunction<ReactiveRemoteJWKSource, ConfigurableJWTProcessor<JWKSecurityContext>, Mono<ConfigurableJWTProcessor<JWKSecurityContext>>> jwtProcessorCustomizer;
|
||||||
|
|
||||||
|
private OAuth2TokenValidator<Jwt> validator = JwtValidators.createDefault();
|
||||||
|
|
||||||
private JwkSetUriReactiveJwtDecoderBuilder(String jwkSetUri) {
|
private JwkSetUriReactiveJwtDecoderBuilder(String jwkSetUri) {
|
||||||
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
|
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
|
||||||
this.jwkSetUri = (web) -> Mono.just(jwkSetUri);
|
this.jwkSetUri = (web) -> Mono.just(jwkSetUri);
|
||||||
@@ -456,6 +459,11 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JwkSetUriReactiveJwtDecoderBuilder validator(OAuth2TokenValidator<Jwt> validator) {
|
||||||
|
this.validator = validator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
JwkSetUriReactiveJwtDecoderBuilder jwtProcessorCustomizer(
|
JwkSetUriReactiveJwtDecoderBuilder jwtProcessorCustomizer(
|
||||||
BiFunction<ReactiveRemoteJWKSource, ConfigurableJWTProcessor<JWKSecurityContext>, Mono<ConfigurableJWTProcessor<JWKSecurityContext>>> jwtProcessorCustomizer) {
|
BiFunction<ReactiveRemoteJWKSource, ConfigurableJWTProcessor<JWKSecurityContext>, Mono<ConfigurableJWTProcessor<JWKSecurityContext>>> jwtProcessorCustomizer) {
|
||||||
Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
||||||
@@ -468,7 +476,9 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|||||||
* @return the configured {@link NimbusReactiveJwtDecoder}
|
* @return the configured {@link NimbusReactiveJwtDecoder}
|
||||||
*/
|
*/
|
||||||
public NimbusReactiveJwtDecoder build() {
|
public NimbusReactiveJwtDecoder build() {
|
||||||
return new NimbusReactiveJwtDecoder(processor());
|
NimbusReactiveJwtDecoder decoder = new NimbusReactiveJwtDecoder(processor());
|
||||||
|
decoder.setJwtValidator(this.validator);
|
||||||
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono<JWSKeySelector<JWKSecurityContext>> jwsKeySelector(ReactiveRemoteJWKSource source) {
|
Mono<JWSKeySelector<JWKSecurityContext>> jwsKeySelector(ReactiveRemoteJWKSource source) {
|
||||||
|
|||||||
+16
-1
@@ -332,7 +332,10 @@ public class NimbusJwtDecoderTests {
|
|||||||
.willReturn(new ResponseEntity<>(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks"), HttpStatus.OK));
|
.willReturn(new ResponseEntity<>(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks"), HttpStatus.OK));
|
||||||
given(restOperations.exchange(any(RequestEntity.class), eq(String.class)))
|
given(restOperations.exchange(any(RequestEntity.class), eq(String.class)))
|
||||||
.willReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK));
|
.willReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK));
|
||||||
JwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer).restOperations(restOperations).build();
|
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer)
|
||||||
|
.restOperations(restOperations)
|
||||||
|
.build();
|
||||||
|
jwtDecoder.setJwtValidator(JwtValidators.createDefault());
|
||||||
Jwt jwt = jwtDecoder.decode(SIGNED_JWT);
|
Jwt jwt = jwtDecoder.decode(SIGNED_JWT);
|
||||||
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
||||||
}
|
}
|
||||||
@@ -350,6 +353,18 @@ public class NimbusJwtDecoderTests {
|
|||||||
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodeWhenIssuerLocationThenRejectsMismatchingIssuers() {
|
||||||
|
String issuer = "https://example.org/wrong-issuer";
|
||||||
|
RestOperations restOperations = mock(RestOperations.class);
|
||||||
|
given(restOperations.exchange(any(RequestEntity.class), any(ParameterizedTypeReference.class)))
|
||||||
|
.willReturn(new ResponseEntity<>(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks"), HttpStatus.OK));
|
||||||
|
given(restOperations.exchange(any(RequestEntity.class), eq(String.class)))
|
||||||
|
.willReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK));
|
||||||
|
JwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer).restOperations(restOperations).build();
|
||||||
|
assertThatExceptionOfType(JwtValidationException.class).isThrownBy(() -> jwtDecoder.decode(SIGNED_JWT));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withJwkSetUriWhenNullOrEmptyThenThrowsException() {
|
public void withJwkSetUriWhenNullOrEmptyThenThrowsException() {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
|||||||
+22
-2
@@ -617,11 +617,31 @@ public class NimbusReactiveJwtDecoderTests {
|
|||||||
given(responseSpec.bodyToMono(any(ParameterizedTypeReference.class)))
|
given(responseSpec.bodyToMono(any(ParameterizedTypeReference.class)))
|
||||||
.willReturn(Mono.just(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks")));
|
.willReturn(Mono.just(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks")));
|
||||||
given(spec.retrieve()).willReturn(responseSpec);
|
given(spec.retrieve()).willReturn(responseSpec);
|
||||||
|
NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withIssuerLocation(issuer)
|
||||||
|
.webClient(webClient)
|
||||||
|
.build();
|
||||||
|
jwtDecoder.setJwtValidator(JwtValidators.createDefault());
|
||||||
|
Jwt jwt = jwtDecoder.decode(this.messageReadToken).block();
|
||||||
|
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodeWhenIssuerLocationThenRejectsMismatchingIssuers() {
|
||||||
|
String issuer = "https://example.org/wrong-issuer";
|
||||||
|
WebClient real = WebClient.builder().build();
|
||||||
|
WebClient.RequestHeadersUriSpec spec = spy(real.get());
|
||||||
|
WebClient webClient = spy(WebClient.class);
|
||||||
|
given(webClient.get()).willReturn(spec);
|
||||||
|
WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class);
|
||||||
|
given(responseSpec.bodyToMono(String.class)).willReturn(Mono.just(this.jwkSet));
|
||||||
|
given(responseSpec.bodyToMono(any(ParameterizedTypeReference.class)))
|
||||||
|
.willReturn(Mono.just(Map.of("issuer", issuer, "jwks_uri", issuer + "/jwks")));
|
||||||
|
given(spec.retrieve()).willReturn(responseSpec);
|
||||||
ReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withIssuerLocation(issuer)
|
ReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withIssuerLocation(issuer)
|
||||||
.webClient(webClient)
|
.webClient(webClient)
|
||||||
.build();
|
.build();
|
||||||
Jwt jwt = jwtDecoder.decode(this.messageReadToken).block();
|
assertThatExceptionOfType(JwtValidationException.class)
|
||||||
assertThat(jwt.hasClaim(JwtClaimNames.EXP)).isNotNull();
|
.isThrownBy(() -> jwtDecoder.decode(this.messageReadToken).block());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user