|
@@ -44,6 +44,7 @@ import com.nimbusds.jwt.JWTClaimsSet;
|
|
|
import com.nimbusds.jwt.JWTParser;
|
|
|
import com.nimbusds.jwt.PlainJWT;
|
|
|
import com.nimbusds.jwt.SignedJWT;
|
|
|
+import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
|
|
|
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
|
|
|
import com.nimbusds.jwt.proc.JWTProcessor;
|
|
|
import reactor.core.publisher.Flux;
|
|
@@ -245,10 +246,12 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
private final String jwkSetUri;
|
|
|
private Set<SignatureAlgorithm> signatureAlgorithms = new HashSet<>();
|
|
|
private WebClient webClient = WebClient.create();
|
|
|
+ private Consumer<ConfigurableJWTProcessor<JWKSecurityContext>> jwtProcessorCustomizer;
|
|
|
|
|
|
private JwkSetUriReactiveJwtDecoderBuilder(String jwkSetUri) {
|
|
|
Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty");
|
|
|
this.jwkSetUri = jwkSetUri;
|
|
|
+ this.jwtProcessorCustomizer = (processor) -> {};
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -294,6 +297,20 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before
|
|
|
+ * passing it to the build {@link NimbusReactiveJwtDecoder}.
|
|
|
+ *
|
|
|
+ * @param jwtProcessorCustomizer the callback used to alter the processor
|
|
|
+ * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations
|
|
|
+ * @since 5.4
|
|
|
+ */
|
|
|
+ public JwkSetUriReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer<ConfigurableJWTProcessor<JWKSecurityContext>> jwtProcessorCustomizer) {
|
|
|
+ Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
|
|
+ this.jwtProcessorCustomizer = jwtProcessorCustomizer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Build the configured {@link NimbusReactiveJwtDecoder}.
|
|
|
*
|
|
@@ -323,6 +340,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
jwtProcessor.setJWSKeySelector(jwsKeySelector);
|
|
|
jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {});
|
|
|
|
|
|
+ this.jwtProcessorCustomizer.accept(jwtProcessor);
|
|
|
+
|
|
|
ReactiveRemoteJWKSource source = new ReactiveRemoteJWKSource(this.jwkSetUri);
|
|
|
source.setWebClient(this.webClient);
|
|
|
|
|
@@ -360,11 +379,13 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
public static final class PublicKeyReactiveJwtDecoderBuilder {
|
|
|
private final RSAPublicKey key;
|
|
|
private JWSAlgorithm jwsAlgorithm;
|
|
|
+ private Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer;
|
|
|
|
|
|
private PublicKeyReactiveJwtDecoderBuilder(RSAPublicKey key) {
|
|
|
Assert.notNull(key, "key cannot be null");
|
|
|
this.key = key;
|
|
|
this.jwsAlgorithm = JWSAlgorithm.RS256;
|
|
|
+ this.jwtProcessorCustomizer = (processor) -> {};
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -382,6 +403,20 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before
|
|
|
+ * passing it to the build {@link NimbusReactiveJwtDecoder}.
|
|
|
+ *
|
|
|
+ * @param jwtProcessorCustomizer the callback used to alter the processor
|
|
|
+ * @return a {@link PublicKeyReactiveJwtDecoderBuilder} for further configurations
|
|
|
+ * @since 5.4
|
|
|
+ */
|
|
|
+ public PublicKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer) {
|
|
|
+ Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
|
|
+ this.jwtProcessorCustomizer = jwtProcessorCustomizer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Build the configured {@link NimbusReactiveJwtDecoder}.
|
|
|
*
|
|
@@ -406,6 +441,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
// Spring Security validates the claim set independent from Nimbus
|
|
|
jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { });
|
|
|
|
|
|
+ this.jwtProcessorCustomizer.accept(jwtProcessor);
|
|
|
+
|
|
|
return jwt -> Mono.just(createClaimsSet(jwtProcessor, jwt, null));
|
|
|
}
|
|
|
}
|
|
@@ -418,10 +455,12 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
public static final class SecretKeyReactiveJwtDecoderBuilder {
|
|
|
private final SecretKey secretKey;
|
|
|
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm.HS256;
|
|
|
+ private Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer;
|
|
|
|
|
|
private SecretKeyReactiveJwtDecoderBuilder(SecretKey secretKey) {
|
|
|
Assert.notNull(secretKey, "secretKey cannot be null");
|
|
|
this.secretKey = secretKey;
|
|
|
+ this.jwtProcessorCustomizer = (processor) -> {};
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -441,6 +480,20 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before
|
|
|
+ * passing it to the build {@link NimbusReactiveJwtDecoder}.
|
|
|
+ *
|
|
|
+ * @param jwtProcessorCustomizer the callback used to alter the processor
|
|
|
+ * @return a {@link SecretKeyReactiveJwtDecoderBuilder} for further configurations
|
|
|
+ * @since 5.4
|
|
|
+ */
|
|
|
+ public SecretKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer<ConfigurableJWTProcessor<SecurityContext>> jwtProcessorCustomizer) {
|
|
|
+ Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
|
|
+ this.jwtProcessorCustomizer = jwtProcessorCustomizer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Build the configured {@link NimbusReactiveJwtDecoder}.
|
|
|
*
|
|
@@ -459,6 +512,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
// Spring Security validates the claim set independent from Nimbus
|
|
|
jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { });
|
|
|
|
|
|
+ this.jwtProcessorCustomizer.accept(jwtProcessor);
|
|
|
+
|
|
|
return jwt -> Mono.just(createClaimsSet(jwtProcessor, jwt, null));
|
|
|
}
|
|
|
}
|
|
@@ -471,10 +526,12 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
public static final class JwkSourceReactiveJwtDecoderBuilder {
|
|
|
private final Function<SignedJWT, Flux<JWK>> jwkSource;
|
|
|
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm.RS256;
|
|
|
+ private Consumer<ConfigurableJWTProcessor<JWKSecurityContext>> jwtProcessorCustomizer;
|
|
|
|
|
|
private JwkSourceReactiveJwtDecoderBuilder(Function<SignedJWT, Flux<JWK>> jwkSource) {
|
|
|
Assert.notNull(jwkSource, "jwkSource cannot be null");
|
|
|
this.jwkSource = jwkSource;
|
|
|
+ this.jwtProcessorCustomizer = (processor) -> {};
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -490,6 +547,20 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before
|
|
|
+ * passing it to the build {@link NimbusReactiveJwtDecoder}.
|
|
|
+ *
|
|
|
+ * @param jwtProcessorCustomizer the callback used to alter the processor
|
|
|
+ * @return a {@link JwkSourceReactiveJwtDecoderBuilder} for further configurations
|
|
|
+ * @since 5.4
|
|
|
+ */
|
|
|
+ public JwkSourceReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer<ConfigurableJWTProcessor<JWKSecurityContext>> jwtProcessorCustomizer) {
|
|
|
+ Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null");
|
|
|
+ this.jwtProcessorCustomizer = jwtProcessorCustomizer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Build the configured {@link NimbusReactiveJwtDecoder}.
|
|
|
*
|
|
@@ -507,6 +578,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
|
|
|
jwtProcessor.setJWSKeySelector(jwsKeySelector);
|
|
|
jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {});
|
|
|
|
|
|
+ this.jwtProcessorCustomizer.accept(jwtProcessor);
|
|
|
+
|
|
|
return jwt -> {
|
|
|
if (jwt instanceof SignedJWT) {
|
|
|
return this.jwkSource.apply((SignedJWT) jwt)
|