@@ -264,11 +264,12 @@ public static SecretKeyJwtDecoderBuilder withSecretKey(SecretKey secretKey) {
264264 /**
265265 * Use the given <a href="https://tools.ietf.org/html/rfc7517#section-5">JWK Set</a>
266266 * uri.
267- * @param jwkSetUri the JWK Set uri to use
267+ * @param jwkSource the JWK Set uri to use
268268 * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations
269+ * @since 7.0
269270 */
270- public static JwkSetUriJwtDecoderBuilder withJwkSource (JWKSource <SecurityContext > jwkSetUri ) {
271- return new JwkSetUriJwtDecoderBuilder ( jwkSetUri );
271+ public static JwkSourceJwtDecoderBuilder withJwkSource (JWKSource <SecurityContext > jwkSource ) {
272+ return new JwkSourceJwtDecoderBuilder ( jwkSource );
272273 }
273274
274275 /**
@@ -813,4 +814,105 @@ JWTProcessor<SecurityContext> processor() {
813814
814815 }
815816
817+ /**
818+ * A builder for creating {@link NimbusJwtDecoder} instances based on a
819+ * <a target="_blank" href="https://tools.ietf.org/html/rfc7517#section-5">JWK Set</a>
820+ * uri.
821+ *
822+ * @since 7.0
823+ */
824+ public static final class JwkSourceJwtDecoderBuilder {
825+
826+ private Set <JWSAlgorithm > defaultAlgorithms = Set .of (JWSAlgorithm .RS256 );
827+
828+ private final Set <SignatureAlgorithm > signatureAlgorithms = new HashSet <>();
829+
830+ private final JWKSource <SecurityContext > jwkSource ;
831+
832+ private Consumer <ConfigurableJWTProcessor <SecurityContext >> jwtProcessorCustomizer ;
833+
834+ private JwkSourceJwtDecoderBuilder (JWKSource <SecurityContext > jwkSource ) {
835+ Assert .notNull (jwkSource , "jwkSource cannot be null" );
836+ this .jwkSource = jwkSource ;
837+ this .jwtProcessorCustomizer = (processor ) -> {
838+ };
839+ }
840+
841+ /**
842+ * Append the given signing
843+ * <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1" target=
844+ * "_blank">algorithm</a> to the set of algorithms to use.
845+ * @param signatureAlgorithm the algorithm to use
846+ * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations
847+ */
848+ public JwkSourceJwtDecoderBuilder jwsAlgorithm (SignatureAlgorithm signatureAlgorithm ) {
849+ Assert .notNull (signatureAlgorithm , "signatureAlgorithm cannot be null" );
850+ this .signatureAlgorithms .add (signatureAlgorithm );
851+ return this ;
852+ }
853+
854+ /**
855+ * Configure the list of
856+ * <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1" target=
857+ * "_blank">algorithms</a> to use with the given {@link Consumer}.
858+ * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring
859+ * the algorithm list
860+ * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations
861+ */
862+ public JwkSourceJwtDecoderBuilder jwsAlgorithms (Consumer <Set <SignatureAlgorithm >> signatureAlgorithmsConsumer ) {
863+ Assert .notNull (signatureAlgorithmsConsumer , "signatureAlgorithmsConsumer cannot be null" );
864+ signatureAlgorithmsConsumer .accept (this .signatureAlgorithms );
865+ return this ;
866+ }
867+
868+ /**
869+ * Use the given {@link Consumer} to customize the {@link JWTProcessor
870+ * ConfigurableJWTProcessor} before passing it to the build
871+ * {@link NimbusJwtDecoder}.
872+ * @param jwtProcessorCustomizer the callback used to alter the processor
873+ * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations
874+ * @since 5.4
875+ */
876+ public JwkSourceJwtDecoderBuilder jwtProcessorCustomizer (
877+ Consumer <ConfigurableJWTProcessor <SecurityContext >> jwtProcessorCustomizer ) {
878+ Assert .notNull (jwtProcessorCustomizer , "jwtProcessorCustomizer cannot be null" );
879+ this .jwtProcessorCustomizer = jwtProcessorCustomizer ;
880+ return this ;
881+ }
882+
883+ JWSKeySelector <SecurityContext > jwsKeySelector () {
884+ if (this .signatureAlgorithms .isEmpty ()) {
885+ return new JWSVerificationKeySelector <>(this .defaultAlgorithms , this .jwkSource );
886+ }
887+ Set <JWSAlgorithm > jwsAlgorithms = new HashSet <>();
888+ for (SignatureAlgorithm signatureAlgorithm : this .signatureAlgorithms ) {
889+ JWSAlgorithm jwsAlgorithm = JWSAlgorithm .parse (signatureAlgorithm .getName ());
890+ jwsAlgorithms .add (jwsAlgorithm );
891+ }
892+ return new JWSVerificationKeySelector <>(jwsAlgorithms , this .jwkSource );
893+ }
894+
895+ /**
896+ * Build the configured {@link NimbusJwtDecoder}.
897+ * @return the configured {@link NimbusJwtDecoder}
898+ */
899+ public NimbusJwtDecoder build () {
900+ return new NimbusJwtDecoder (processor ());
901+ }
902+
903+ JWTProcessor <SecurityContext > processor () {
904+ ConfigurableJWTProcessor <SecurityContext > jwtProcessor = new DefaultJWTProcessor <>();
905+ // Spring Security validates the claim set independent from Nimbus
906+ jwtProcessor .setJWSTypeVerifier ((header , context ) -> {
907+ });
908+ jwtProcessor .setJWSKeySelector (jwsKeySelector ());
909+ // Spring Security validates the claim set independent from Nimbus
910+ jwtProcessor .setJWTClaimsSetVerifier ((claims , context ) -> {
911+ });
912+ this .jwtProcessorCustomizer .accept (jwtProcessor );
913+ return jwtProcessor ;
914+ }
915+
916+ }
917+
816918}
0 commit comments