@@ -261,6 +261,16 @@ public static SecretKeyJwtDecoderBuilder withSecretKey(SecretKey secretKey) {
261
261
return new SecretKeyJwtDecoderBuilder (secretKey );
262
262
}
263
263
264
+ /**
265
+ * Use the given {@code JWKSource} to create a JwkSourceJwtDecoderBuilder.
266
+ * @param jwkSource the JWK Source to use
267
+ * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations
268
+ * @since 7.0
269
+ */
270
+ public static JwkSourceJwtDecoderBuilder withJwkSource (JWKSource <SecurityContext > jwkSource ) {
271
+ return new JwkSourceJwtDecoderBuilder (jwkSource );
272
+ }
273
+
264
274
/**
265
275
* A builder for creating {@link NimbusJwtDecoder} instances based on a
266
276
* <a target="_blank" href="https://tools.ietf.org/html/rfc7517#section-5">JWK Set</a>
@@ -535,6 +545,106 @@ public void close() {
535
545
536
546
}
537
547
548
+ /**
549
+ * A builder for creating {@link NimbusJwtDecoder} instances based on a {@code JWKSource}.
550
+ */
551
+ public static final class JwkSourceJwtDecoderBuilder {
552
+
553
+ private static final JOSEObjectTypeVerifier <SecurityContext > NO_TYPE_VERIFIER = (header , context ) -> {
554
+ };
555
+
556
+ private final Function <JWKSource <SecurityContext >, Set <JWSAlgorithm >> defaultAlgorithms = (source ) -> Set
557
+ .of (JWSAlgorithm .RS256 );
558
+
559
+ private final JOSEObjectTypeVerifier <SecurityContext > typeVerifier = NO_TYPE_VERIFIER ;
560
+
561
+ private final Set <SignatureAlgorithm > signatureAlgorithms = new HashSet <>();
562
+
563
+ private Consumer <ConfigurableJWTProcessor <SecurityContext >> jwtProcessorCustomizer ;
564
+
565
+ private final JWKSource <SecurityContext > jwkSource ;
566
+
567
+ private JwkSourceJwtDecoderBuilder (JWKSource <SecurityContext > jwkSource ) {
568
+ Assert .notNull (jwkSource , "jwkSource cannot be null" );
569
+ this .jwkSource = jwkSource ;
570
+ this .jwtProcessorCustomizer = (processor ) -> {
571
+ };
572
+ }
573
+
574
+ /**
575
+ * Append the given signing
576
+ * <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1" target=
577
+ * "_blank">algorithm</a> to the set of algorithms to use.
578
+ * @param signatureAlgorithm the algorithm to use
579
+ * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations
580
+ */
581
+ public JwkSourceJwtDecoderBuilder jwsAlgorithm (SignatureAlgorithm signatureAlgorithm ) {
582
+ Assert .notNull (signatureAlgorithm , "signatureAlgorithm cannot be null" );
583
+ this .signatureAlgorithms .add (signatureAlgorithm );
584
+ return this ;
585
+ }
586
+
587
+ /**
588
+ * Configure the list of
589
+ * <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1" target=
590
+ * "_blank">algorithms</a> to use with the given {@link Consumer}.
591
+ * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring
592
+ * the algorithm list
593
+ * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations
594
+ */
595
+ public JwkSourceJwtDecoderBuilder jwsAlgorithms (Consumer <Set <SignatureAlgorithm >> signatureAlgorithmsConsumer ) {
596
+ Assert .notNull (signatureAlgorithmsConsumer , "signatureAlgorithmsConsumer cannot be null" );
597
+ signatureAlgorithmsConsumer .accept (this .signatureAlgorithms );
598
+ return this ;
599
+ }
600
+
601
+ /**
602
+ * Use the given {@link Consumer} to customize the {@link JWTProcessor
603
+ * ConfigurableJWTProcessor} before passing it to the build
604
+ * {@link NimbusJwtDecoder}.
605
+ * @param jwtProcessorCustomizer the callback used to alter the processor
606
+ * @return a {@link JwkSourceJwtDecoderBuilder } for further configurations
607
+ * @since 5.4
608
+ */
609
+ public JwkSourceJwtDecoderBuilder jwtProcessorCustomizer (
610
+ Consumer <ConfigurableJWTProcessor <SecurityContext >> jwtProcessorCustomizer ) {
611
+ Assert .notNull (jwtProcessorCustomizer , "jwtProcessorCustomizer cannot be null" );
612
+ this .jwtProcessorCustomizer = jwtProcessorCustomizer ;
613
+ return this ;
614
+ }
615
+
616
+ JWSKeySelector <SecurityContext > jwsKeySelector (JWKSource <SecurityContext > jwkSource ) {
617
+ if (this .signatureAlgorithms .isEmpty ()) {
618
+ return new JWSVerificationKeySelector <>(this .defaultAlgorithms .apply (jwkSource ), jwkSource );
619
+ }
620
+ Set <JWSAlgorithm > jwsAlgorithms = new HashSet <>();
621
+ for (SignatureAlgorithm signatureAlgorithm : this .signatureAlgorithms ) {
622
+ JWSAlgorithm jwsAlgorithm = JWSAlgorithm .parse (signatureAlgorithm .getName ());
623
+ jwsAlgorithms .add (jwsAlgorithm );
624
+ }
625
+ return new JWSVerificationKeySelector <>(jwsAlgorithms , jwkSource );
626
+ }
627
+
628
+ JWTProcessor <SecurityContext > processor () {
629
+ ConfigurableJWTProcessor <SecurityContext > jwtProcessor = new DefaultJWTProcessor <>();
630
+ jwtProcessor .setJWSTypeVerifier (this .typeVerifier );
631
+ jwtProcessor .setJWSKeySelector (jwsKeySelector (jwkSource ));
632
+ // Spring Security validates the claim set independent from Nimbus
633
+ jwtProcessor .setJWTClaimsSetVerifier ((claims , context ) -> {
634
+ });
635
+ this .jwtProcessorCustomizer .accept (jwtProcessor );
636
+ return jwtProcessor ;
637
+ }
638
+
639
+ /**
640
+ * Build the configured {@link NimbusJwtDecoder}.
641
+ * @return the configured {@link NimbusJwtDecoder}
642
+ */
643
+ public NimbusJwtDecoder build () {
644
+ return new NimbusJwtDecoder (processor ());
645
+ }
646
+ }
647
+
538
648
/**
539
649
* A builder for creating {@link NimbusJwtDecoder} instances based on a public key.
540
650
*/
0 commit comments