From d52e0b6a051d817c9af0c4ab8bc714b3233a9842 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 2 Jun 2025 15:53:27 -0600 Subject: [PATCH] Polish NimbusJwtDecoder - Aligned JwkSourceJwtDecoderBuilder's relative position with its corresponding static factory - Added @since to JwkSourceJwtDecoderBuilder PR gh-17046 --- .../security/oauth2/jwt/NimbusJwtDecoder.java | 206 +++++++++--------- 1 file changed, 104 insertions(+), 102 deletions(-) diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java index d762e919ac..776f4e7335 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java @@ -545,108 +545,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { } - /** - * A builder for creating {@link NimbusJwtDecoder} instances based on a - * {@code JWKSource}. - */ - public static final class JwkSourceJwtDecoderBuilder { - - private static final JOSEObjectTypeVerifier NO_TYPE_VERIFIER = (header, context) -> { - }; - - private final Function, Set> defaultAlgorithms = (source) -> Set - .of(JWSAlgorithm.RS256); - - private final JOSEObjectTypeVerifier typeVerifier = NO_TYPE_VERIFIER; - - private final Set signatureAlgorithms = new HashSet<>(); - - private Consumer> jwtProcessorCustomizer; - - private final JWKSource jwkSource; - - private JwkSourceJwtDecoderBuilder(JWKSource jwkSource) { - Assert.notNull(jwkSource, "jwkSource cannot be null"); - this.jwkSource = jwkSource; - this.jwtProcessorCustomizer = (processor) -> { - }; - } - - /** - * Append the given signing - * algorithm to the set of algorithms to use. - * @param signatureAlgorithm the algorithm to use - * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations - */ - public JwkSourceJwtDecoderBuilder jwsAlgorithm(SignatureAlgorithm signatureAlgorithm) { - Assert.notNull(signatureAlgorithm, "signatureAlgorithm cannot be null"); - this.signatureAlgorithms.add(signatureAlgorithm); - return this; - } - - /** - * Configure the list of - * algorithms to use with the given {@link Consumer}. - * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring - * the algorithm list - * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations - */ - public JwkSourceJwtDecoderBuilder jwsAlgorithms(Consumer> signatureAlgorithmsConsumer) { - Assert.notNull(signatureAlgorithmsConsumer, "signatureAlgorithmsConsumer cannot be null"); - signatureAlgorithmsConsumer.accept(this.signatureAlgorithms); - return this; - } - - /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor - * ConfigurableJWTProcessor} before passing it to the build - * {@link NimbusJwtDecoder}. - * @param jwtProcessorCustomizer the callback used to alter the processor - * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations - * @since 5.4 - */ - public JwkSourceJwtDecoderBuilder jwtProcessorCustomizer( - Consumer> jwtProcessorCustomizer) { - Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); - this.jwtProcessorCustomizer = jwtProcessorCustomizer; - return this; - } - - JWSKeySelector jwsKeySelector(JWKSource jwkSource) { - if (this.signatureAlgorithms.isEmpty()) { - return new JWSVerificationKeySelector<>(this.defaultAlgorithms.apply(jwkSource), jwkSource); - } - Set jwsAlgorithms = new HashSet<>(); - for (SignatureAlgorithm signatureAlgorithm : this.signatureAlgorithms) { - JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(signatureAlgorithm.getName()); - jwsAlgorithms.add(jwsAlgorithm); - } - return new JWSVerificationKeySelector<>(jwsAlgorithms, jwkSource); - } - - JWTProcessor processor() { - ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); - jwtProcessor.setJWSTypeVerifier(this.typeVerifier); - jwtProcessor.setJWSKeySelector(jwsKeySelector(this.jwkSource)); - // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { - }); - this.jwtProcessorCustomizer.accept(jwtProcessor); - return jwtProcessor; - } - - /** - * Build the configured {@link NimbusJwtDecoder}. - * @return the configured {@link NimbusJwtDecoder} - */ - public NimbusJwtDecoder build() { - return new NimbusJwtDecoder(processor()); - } - - } - /** * A builder for creating {@link NimbusJwtDecoder} instances based on a public key. */ @@ -903,4 +801,108 @@ public final class NimbusJwtDecoder implements JwtDecoder { } + /** + * A builder for creating {@link NimbusJwtDecoder} instances based on a + * {@code JWKSource}. + * + * @since 7.0 + */ + public static final class JwkSourceJwtDecoderBuilder { + + private static final JOSEObjectTypeVerifier NO_TYPE_VERIFIER = (header, context) -> { + }; + + private final Function, Set> defaultAlgorithms = (source) -> Set + .of(JWSAlgorithm.RS256); + + private final JOSEObjectTypeVerifier typeVerifier = NO_TYPE_VERIFIER; + + private final Set signatureAlgorithms = new HashSet<>(); + + private Consumer> jwtProcessorCustomizer; + + private final JWKSource jwkSource; + + private JwkSourceJwtDecoderBuilder(JWKSource jwkSource) { + Assert.notNull(jwkSource, "jwkSource cannot be null"); + this.jwkSource = jwkSource; + this.jwtProcessorCustomizer = (processor) -> { + }; + } + + /** + * Append the given signing + * algorithm to the set of algorithms to use. + * @param signatureAlgorithm the algorithm to use + * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations + */ + public JwkSourceJwtDecoderBuilder jwsAlgorithm(SignatureAlgorithm signatureAlgorithm) { + Assert.notNull(signatureAlgorithm, "signatureAlgorithm cannot be null"); + this.signatureAlgorithms.add(signatureAlgorithm); + return this; + } + + /** + * Configure the list of + * algorithms to use with the given {@link Consumer}. + * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring + * the algorithm list + * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations + */ + public JwkSourceJwtDecoderBuilder jwsAlgorithms(Consumer> signatureAlgorithmsConsumer) { + Assert.notNull(signatureAlgorithmsConsumer, "signatureAlgorithmsConsumer cannot be null"); + signatureAlgorithmsConsumer.accept(this.signatureAlgorithms); + return this; + } + + /** + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusJwtDecoder}. + * @param jwtProcessorCustomizer the callback used to alter the processor + * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations + * @since 5.4 + */ + public JwkSourceJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { + Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); + this.jwtProcessorCustomizer = jwtProcessorCustomizer; + return this; + } + + JWSKeySelector jwsKeySelector(JWKSource jwkSource) { + if (this.signatureAlgorithms.isEmpty()) { + return new JWSVerificationKeySelector<>(this.defaultAlgorithms.apply(jwkSource), jwkSource); + } + Set jwsAlgorithms = new HashSet<>(); + for (SignatureAlgorithm signatureAlgorithm : this.signatureAlgorithms) { + JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(signatureAlgorithm.getName()); + jwsAlgorithms.add(jwsAlgorithm); + } + return new JWSVerificationKeySelector<>(jwsAlgorithms, jwkSource); + } + + JWTProcessor processor() { + ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); + jwtProcessor.setJWSTypeVerifier(this.typeVerifier); + jwtProcessor.setJWSKeySelector(jwsKeySelector(this.jwkSource)); + // Spring Security validates the claim set independent from Nimbus + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); + this.jwtProcessorCustomizer.accept(jwtProcessor); + return jwtProcessor; + } + + /** + * Build the configured {@link NimbusJwtDecoder}. + * @return the configured {@link NimbusJwtDecoder} + */ + public NimbusJwtDecoder build() { + return new NimbusJwtDecoder(processor()); + } + + } + }