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