From aac9194a2266a9742cb59a852bc6828e5499eaae Mon Sep 17 00:00:00 2001 From: Krzysztof P Date: Wed, 9 Sep 2020 15:45:20 +0200 Subject: [PATCH 1/4] Allow for customization of IssuerConverter and JwtAuthenticationConverter Customization of IssuerConverter and JwtAuthenticationConverter will make it easier to customize the way JWTs are handled, especially in a multi-tenant env, with the use of the default JwtAuthenticationProvider. This eliminates the need to write a complex implementation for different tasks, that ideally should be quick and easy, such as custom GranthedAuthorities conversion. Closes gh-8535 --- ...wtIssuerAuthenticationManagerResolver.java | 81 ++++++++++++++++++- ...ReactiveAuthenticationManagerResolver.java | 80 +++++++++++++++++- ...uerAuthenticationManagerResolverTests.java | 49 +++++++++++ ...iveAuthenticationManagerResolverTests.java | 42 ++++++++++ 4 files changed, 246 insertions(+), 6 deletions(-) diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java index af1cddc205d..331ca906258 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java @@ -65,7 +65,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat private final AuthenticationManagerResolver issuerAuthenticationManagerResolver; - private final Converter issuerConverter = new JwtClaimIssuerConverter(); + private final Converter issuerConverter; /** * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided @@ -85,6 +85,30 @@ public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers) Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( Collections.unmodifiableCollection(trustedIssuers)::contains); + this.issuerConverter = new JwtClaimIssuerConverter(); + } + + /** + * Construct a {@link JwtIssuerAuthenticationManagerResolver} with + * a custom {@link JwtAuthenticationConverter} using the provided parameters + * + * A custom {@link JwtAuthenticationConverter} allows to use a + * custom {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) + * to handle an untypical JWT token + * + * @param trustedIssuers a list of trusted issuers + * @param jwtAuthenticationConverter a custom {@link JwtAuthenticationConverter} + * @since 5.4 + */ + public JwtIssuerAuthenticationManagerResolver( + Collection trustedIssuers, + JwtAuthenticationConverter jwtAuthenticationConverter) { + Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); + Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); + this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( + Collections.unmodifiableCollection(trustedIssuers)::contains, + jwtAuthenticationConverter); + this.issuerConverter = new JwtClaimIssuerConverter(); } /** @@ -110,8 +134,43 @@ public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers) */ public JwtIssuerAuthenticationManagerResolver( AuthenticationManagerResolver issuerAuthenticationManagerResolver) { + this(issuerAuthenticationManagerResolver, new JwtClaimIssuerConverter()); + } + + /** + * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided + * parameters + * + * Note that the {@link AuthenticationManagerResolver} provided in this constructor + * will need to verify that the issuer is trusted. This should be done via an + * allowlist. + * + * One way to achieve this is with a {@link Map} where the keys are the known issuers: + *
+	 *     Map<String, AuthenticationManager> authenticationManagers = new HashMap<>();
+	 *     authenticationManagers.put("https://issuerOne.example.org", managerOne);
+	 *     authenticationManagers.put("https://issuerTwo.example.org", managerTwo);
+	 *     JwtAuthenticationManagerResolver resolver = new JwtAuthenticationManagerResolver
+	 *     	(authenticationManagers::get);
+	 * 
+ * + * The keys in the {@link Map} are the allowed issuers. + * + * @param issuerAuthenticationManagerResolver a strategy for resolving the + * {@link AuthenticationManager} by the issuer + * + * @param issuerConverter a custom converter to resolve the token + * A custom converter allows to use a custom {@link BearerTokenResolver} + * + * @since 5.4 + */ + public JwtIssuerAuthenticationManagerResolver( + AuthenticationManagerResolver issuerAuthenticationManagerResolver, + Converter issuerConverter){ Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); + Assert.notNull(issuerConverter, "issuerConverter cannot be null"); this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; + this.issuerConverter = issuerConverter; } /** @@ -160,8 +219,17 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver private final Predicate trustedIssuer; + private final JwtAuthenticationConverter jwtAuthenticationConverter; + TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer) { + this(trustedIssuer, null); + } + + TrustedIssuerJwtAuthenticationManagerResolver( + Predicate trustedIssuer, + JwtAuthenticationConverter jwtAuthenticationConverter) { this.trustedIssuer = trustedIssuer; + this.jwtAuthenticationConverter = jwtAuthenticationConverter; } @Override @@ -171,7 +239,16 @@ public AuthenticationManager resolve(String issuer) { (k) -> { this.logger.debug("Constructing AuthenticationManager"); JwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuer); - return new JwtAuthenticationProvider(jwtDecoder)::authenticate; + if(jwtAuthenticationConverter != null) { + this.logger.debug(("Using custom JwtAuthenticationConverter")); + final JwtAuthenticationProvider jwtAuthenticationProvider = + new JwtAuthenticationProvider(jwtDecoder); + jwtAuthenticationProvider.setJwtAuthenticationConverter(jwtAuthenticationConverter); + return jwtAuthenticationProvider::authenticate; + } else { + this.logger.debug(("Using default JwtAuthenticationConverter")); + return new JwtAuthenticationProvider(jwtDecoder)::authenticate; + } }); this.logger.debug(LogMessage.format("Resolved AuthenticationManager for issuer '%s'", issuer)); return authenticationManager; diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java index e73635e887d..d625df362ac 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java @@ -65,7 +65,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver private final ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver; - private final Converter> issuerConverter = new JwtClaimIssuerConverter(); + private final Converter> issuerConverter; /** * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the @@ -85,6 +85,28 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection trusted Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( new ArrayList<>(trustedIssuers)::contains); + this.issuerConverter = new JwtClaimIssuerConverter(); + } + + /** + * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the + * provided parameters + * + * A custom {@link ReactiveJwtAuthenticationConverterAdapter} allows to use a + * custom {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) + * to handle an untypical JWT token + * + * @param trustedIssuers a collection of trusted issuers + * @param reactiveJwtAuthenticationConverterAdapter a custom {@link ReactiveJwtAuthenticationConverterAdapter} + */ + public JwtIssuerReactiveAuthenticationManagerResolver( + Collection trustedIssuers, + ReactiveJwtAuthenticationConverterAdapter reactiveJwtAuthenticationConverterAdapter) { + Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); + this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( + new ArrayList<>(trustedIssuers)::contains, + reactiveJwtAuthenticationConverterAdapter); + this.issuerConverter = new JwtClaimIssuerConverter(); } /** @@ -110,8 +132,40 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection trusted */ public JwtIssuerReactiveAuthenticationManagerResolver( ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver) { + this(issuerAuthenticationManagerResolver, new JwtClaimIssuerConverter()); + } + + /** + * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the + * provided parameters + * + * Note that the {@link ReactiveAuthenticationManagerResolver} provided in this + * constructor will need to verify that the issuer is trusted. This should be done via + * an allowed list of issuers. + * + * One way to achieve this is with a {@link Map} where the keys are the known issuers: + *
+	 *     Map<String, ReactiveAuthenticationManager> authenticationManagers = new HashMap<>();
+	 *     authenticationManagers.put("https://issuerOne.example.org", managerOne);
+	 *     authenticationManagers.put("https://issuerTwo.example.org", managerTwo);
+	 *     JwtIssuerReactiveAuthenticationManagerResolver resolver = new JwtIssuerReactiveAuthenticationManagerResolver
+	 *     	((issuer) -> Mono.justOrEmpty(authenticationManagers.get(issuer));
+	 * 
+ * + * The keys in the {@link Map} are the trusted issuers. + * @param issuerAuthenticationManagerResolver a strategy for resolving the + * {@link ReactiveAuthenticationManager} by the issuer + * + * @param issuerConverter a custom converter to resolve the token + * A custom converter allows to use a custom {@link ServerBearerTokenAuthenticationConverter} + */ + public JwtIssuerReactiveAuthenticationManagerResolver( + ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver, + Converter> issuerConverter) { Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); + Assert.notNull(issuerConverter, "issuerConverter cannot be null"); this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; + this.issuerConverter = new JwtClaimIssuerConverter(); } /** @@ -161,8 +215,17 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver private final Predicate trustedIssuer; + private final ReactiveJwtAuthenticationConverterAdapter jwtAuthenticationConverterAdapter; + TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer) { + this(trustedIssuer, null); + } + + TrustedIssuerJwtAuthenticationManagerResolver( + Predicate trustedIssuer, + ReactiveJwtAuthenticationConverterAdapter jwtAuthenticationConverterAdapter) { this.trustedIssuer = trustedIssuer; + this.jwtAuthenticationConverterAdapter = jwtAuthenticationConverterAdapter; } @Override @@ -172,9 +235,18 @@ public Mono resolve(String issuer) { } // @formatter:off return this.authenticationManagers.computeIfAbsent(issuer, - (k) -> Mono.fromCallable(() -> new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k))) - .subscribeOn(Schedulers.boundedElastic()) - .cache() + (k) -> Mono.fromCallable(() -> { + if(jwtAuthenticationConverterAdapter != null) { + final JwtReactiveAuthenticationManager authenticationManager = + new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); + authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverterAdapter); + return authenticationManager; + } else { + return new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .cache() ); // @formatter:on } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java index 354c5511058..9f794cea3e7 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java @@ -33,12 +33,16 @@ import okhttp3.mockwebserver.MockWebServer; import org.junit.Test; +import org.springframework.core.convert.converter.Converter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManagerResolver; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.jose.TestKeys; import org.springframework.security.oauth2.jwt.JwtClaimNames; +import org.springframework.security.oauth2.jwt.JwtDecoders; + +import javax.servlet.http.HttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -84,6 +88,31 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } } + @Test + public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() throws Exception { + try (MockWebServer server = new MockWebServer()) { + server.start(); + String issuer = server.url("").toString(); + // @formatter:off + server.enqueue(new MockResponse().setResponseCode(200) + .setHeader("Content-Type", "application/json") + .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer) + )); + // @formatter:on + JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), + new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); + jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + Collections.singletonList(issuer), new JwtAuthenticationConverter()); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Authorization", "Bearer " + jws.serialize()); + AuthenticationManager authenticationManager = authenticationManagerResolver.resolve(request); + assertThat(authenticationManager).isNotNull(); + AuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(request); + assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); + } + } + @Test public void resolveWhenUsingUntrustedIssuerThenException() { JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( @@ -107,6 +136,17 @@ public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager); } + @Test + public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomIssuerConverterThenUses() { + AuthenticationManager authenticationManager = mock(AuthenticationManager.class); + Converter jwtAuthConverter = (Converter) mock(Converter.class); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + (issuer) -> authenticationManager, jwtAuthConverter); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Authorization", "Bearer " + this.jwt); + assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager); + } + @Test public void resolveWhenUsingExternalSourceThenRespondsToChanges() { MockHttpServletRequest request = new MockHttpServletRequest(); @@ -185,6 +225,15 @@ public void constructorWhenNullAuthenticationManagerResolverThenException() { .isThrownBy(() -> new JwtIssuerAuthenticationManagerResolver((AuthenticationManagerResolver) null)); } + @Test + public void constructWhenNullIssuerConverterThenException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new JwtIssuerAuthenticationManagerResolver( + context -> new JwtAuthenticationProvider( + JwtDecoders.fromIssuerLocation("trusted"))::authenticate, null) + ); + } + private String jwt(String claim, String value) { PlainJWT jwt = new PlainJWT(new JWTClaimsSet.Builder().claim(claim, value).build()); return jwt.serialize(); diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java index a794aa1fdeb..c16ca66ae61 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java @@ -32,6 +32,9 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.junit.Test; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders; +import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; @@ -86,6 +89,27 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } } + @Test + public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() throws Exception { + try (MockWebServer server = new MockWebServer()) { + String issuer = server.url("").toString(); + server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json") + .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); + JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), + new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); + jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + Collections.singletonList(issuer), new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter())); + MockServerWebExchange exchange = withBearerToken(jws.serialize()); + ReactiveAuthenticationManager authenticationManager = authenticationManagerResolver.resolve(exchange) + .block(); + assertThat(authenticationManager).isNotNull(); + ReactiveAuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(exchange) + .block(); + assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); + } + } + @Test public void resolveWhenUsingUntrustedIssuerThenException() { JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( @@ -107,6 +131,16 @@ public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager); } + @Test + public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomIssuerConverterThenUses() { + ReactiveAuthenticationManager authenticationManager = mock(ReactiveAuthenticationManager.class); + Converter> jwtAuthConverter = (Converter>) mock(Converter.class); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + (issuer) -> Mono.just(authenticationManager), jwtAuthConverter); + MockServerWebExchange exchange = withBearerToken(this.jwt); + assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager); + } + @Test public void resolveWhenUsingExternalSourceThenRespondsToChanges() { MockServerWebExchange exchange = withBearerToken(this.jwt); @@ -175,6 +209,14 @@ public void constructorWhenNullAuthenticationManagerResolverThenException() { () -> new JwtIssuerReactiveAuthenticationManagerResolver((ReactiveAuthenticationManagerResolver) null)); } + @Test + public void constructWhenNullIssuerConverterThenException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new JwtIssuerReactiveAuthenticationManagerResolver( + context -> Mono.just(new JwtReactiveAuthenticationManager( + ReactiveJwtDecoders.fromIssuerLocation("trusted"))), null)); + } + private String jwt(String claim, String value) { PlainJWT jwt = new PlainJWT(new JWTClaimsSet.Builder().claim(claim, value).build()); return jwt.serialize(); From f8a36638ceca3e40b45074878964a964a5058aa2 Mon Sep 17 00:00:00 2001 From: Krzysztof P Date: Wed, 9 Sep 2020 16:18:00 +0200 Subject: [PATCH 2/4] Allow for customization of IssuerConverter and JwtAuthenticationConverter Customization of IssuerConverter and JwtAuthenticationConverter will make it easier to customize the way JWTs are handled, especially in a multi-tenant env, with the use of the default JwtAuthenticationProvider. This eliminates the need to write a complex implementation for different tasks, that ideally should be quick and easy, such as custom GranthedAuthorities conversion. Closes gh-8535 --- ...wtIssuerAuthenticationManagerResolver.java | 37 ++++++++----------- ...ReactiveAuthenticationManagerResolver.java | 24 +++++------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java index 331ca906258..c5ce1fc95a1 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java @@ -89,25 +89,22 @@ public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers) } /** - * Construct a {@link JwtIssuerAuthenticationManagerResolver} with - * a custom {@link JwtAuthenticationConverter} using the provided parameters - * - * A custom {@link JwtAuthenticationConverter} allows to use a - * custom {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) - * to handle an untypical JWT token + * Construct a {@link JwtIssuerAuthenticationManagerResolver} with a custom + * {@link JwtAuthenticationConverter} using the provided parameters * + * A custom {@link JwtAuthenticationConverter} allows to use a custom + * {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) to handle an + * untypical JWT token * @param trustedIssuers a list of trusted issuers * @param jwtAuthenticationConverter a custom {@link JwtAuthenticationConverter} * @since 5.4 */ - public JwtIssuerAuthenticationManagerResolver( - Collection trustedIssuers, + public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers, JwtAuthenticationConverter jwtAuthenticationConverter) { Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( - Collections.unmodifiableCollection(trustedIssuers)::contains, - jwtAuthenticationConverter); + Collections.unmodifiableCollection(trustedIssuers)::contains, jwtAuthenticationConverter); this.issuerConverter = new JwtClaimIssuerConverter(); } @@ -155,18 +152,16 @@ public JwtIssuerAuthenticationManagerResolver( * * * The keys in the {@link Map} are the allowed issuers. - * * @param issuerAuthenticationManagerResolver a strategy for resolving the * {@link AuthenticationManager} by the issuer - * - * @param issuerConverter a custom converter to resolve the token - * A custom converter allows to use a custom {@link BearerTokenResolver} + * @param issuerConverter a custom converter to resolve the token A custom converter + * allows to use a custom {@link BearerTokenResolver} * * @since 5.4 */ public JwtIssuerAuthenticationManagerResolver( AuthenticationManagerResolver issuerAuthenticationManagerResolver, - Converter issuerConverter){ + Converter issuerConverter) { Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); Assert.notNull(issuerConverter, "issuerConverter cannot be null"); this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; @@ -225,8 +220,7 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver this(trustedIssuer, null); } - TrustedIssuerJwtAuthenticationManagerResolver( - Predicate trustedIssuer, + TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer, JwtAuthenticationConverter jwtAuthenticationConverter) { this.trustedIssuer = trustedIssuer; this.jwtAuthenticationConverter = jwtAuthenticationConverter; @@ -239,13 +233,14 @@ public AuthenticationManager resolve(String issuer) { (k) -> { this.logger.debug("Constructing AuthenticationManager"); JwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuer); - if(jwtAuthenticationConverter != null) { + if (jwtAuthenticationConverter != null) { this.logger.debug(("Using custom JwtAuthenticationConverter")); - final JwtAuthenticationProvider jwtAuthenticationProvider = - new JwtAuthenticationProvider(jwtDecoder); + final JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider( + jwtDecoder); jwtAuthenticationProvider.setJwtAuthenticationConverter(jwtAuthenticationConverter); return jwtAuthenticationProvider::authenticate; - } else { + } + else { this.logger.debug(("Using default JwtAuthenticationConverter")); return new JwtAuthenticationProvider(jwtDecoder)::authenticate; } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java index d625df362ac..be5177767ae 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java @@ -92,20 +92,18 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection trusted * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the * provided parameters * - * A custom {@link ReactiveJwtAuthenticationConverterAdapter} allows to use a - * custom {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) - * to handle an untypical JWT token - * + * A custom {@link ReactiveJwtAuthenticationConverterAdapter} allows to use a custom + * {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) to handle an + * untypical JWT token * @param trustedIssuers a collection of trusted issuers - * @param reactiveJwtAuthenticationConverterAdapter a custom {@link ReactiveJwtAuthenticationConverterAdapter} + * @param reactiveJwtAuthenticationConverterAdapter a custom + * {@link ReactiveJwtAuthenticationConverterAdapter} */ - public JwtIssuerReactiveAuthenticationManagerResolver( - Collection trustedIssuers, + public JwtIssuerReactiveAuthenticationManagerResolver(Collection trustedIssuers, ReactiveJwtAuthenticationConverterAdapter reactiveJwtAuthenticationConverterAdapter) { Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( - new ArrayList<>(trustedIssuers)::contains, - reactiveJwtAuthenticationConverterAdapter); + new ArrayList<>(trustedIssuers)::contains, reactiveJwtAuthenticationConverterAdapter); this.issuerConverter = new JwtClaimIssuerConverter(); } @@ -155,9 +153,8 @@ public JwtIssuerReactiveAuthenticationManagerResolver( * The keys in the {@link Map} are the trusted issuers. * @param issuerAuthenticationManagerResolver a strategy for resolving the * {@link ReactiveAuthenticationManager} by the issuer - * - * @param issuerConverter a custom converter to resolve the token - * A custom converter allows to use a custom {@link ServerBearerTokenAuthenticationConverter} + * @param issuerConverter a custom converter to resolve the token A custom converter + * allows to use a custom {@link ServerBearerTokenAuthenticationConverter} */ public JwtIssuerReactiveAuthenticationManagerResolver( ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver, @@ -221,8 +218,7 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver this(trustedIssuer, null); } - TrustedIssuerJwtAuthenticationManagerResolver( - Predicate trustedIssuer, + TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer, ReactiveJwtAuthenticationConverterAdapter jwtAuthenticationConverterAdapter) { this.trustedIssuer = trustedIssuer; this.jwtAuthenticationConverterAdapter = jwtAuthenticationConverterAdapter; From 3fdb9c21661e86345bdee662f61f0bcca93311bd Mon Sep 17 00:00:00 2001 From: Krzysztof P Date: Wed, 9 Sep 2020 16:26:24 +0200 Subject: [PATCH 3/4] Tests formatting fix for gh-8535 Closes gh-8535 --- ...uerAuthenticationManagerResolverTests.java | 16 ++++++------ ...iveAuthenticationManagerResolverTests.java | 25 +++++++++++-------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java index 9f794cea3e7..1aac9e03ca3 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java @@ -89,7 +89,8 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } @Test - public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() throws Exception { + public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() + throws Exception { try (MockWebServer server = new MockWebServer()) { server.start(); String issuer = server.url("").toString(); @@ -100,7 +101,7 @@ public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAut )); // @formatter:on JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), - new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); + new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( Collections.singletonList(issuer), new JwtAuthenticationConverter()); @@ -139,7 +140,8 @@ public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() @Test public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomIssuerConverterThenUses() { AuthenticationManager authenticationManager = mock(AuthenticationManager.class); - Converter jwtAuthConverter = (Converter) mock(Converter.class); + Converter jwtAuthConverter = (Converter) mock( + Converter.class); JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( (issuer) -> authenticationManager, jwtAuthConverter); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -227,11 +229,9 @@ public void constructorWhenNullAuthenticationManagerResolverThenException() { @Test public void constructWhenNullIssuerConverterThenException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new JwtIssuerAuthenticationManagerResolver( - context -> new JwtAuthenticationProvider( - JwtDecoders.fromIssuerLocation("trusted"))::authenticate, null) - ); + assertThatIllegalArgumentException().isThrownBy(() -> new JwtIssuerAuthenticationManagerResolver( + context -> new JwtAuthenticationProvider(JwtDecoders.fromIssuerLocation("trusted"))::authenticate, + null)); } private String jwt(String claim, String value) { diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java index c16ca66ae61..001ddeb0a0d 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java @@ -90,22 +90,24 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } @Test - public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() throws Exception { + public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() + throws Exception { try (MockWebServer server = new MockWebServer()) { String issuer = server.url("").toString(); server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json") - .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); + .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), - new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); + new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( - Collections.singletonList(issuer), new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter())); + Collections.singletonList(issuer), + new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter())); MockServerWebExchange exchange = withBearerToken(jws.serialize()); ReactiveAuthenticationManager authenticationManager = authenticationManagerResolver.resolve(exchange) - .block(); + .block(); assertThat(authenticationManager).isNotNull(); ReactiveAuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(exchange) - .block(); + .block(); assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); } } @@ -134,7 +136,8 @@ public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() @Test public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomIssuerConverterThenUses() { ReactiveAuthenticationManager authenticationManager = mock(ReactiveAuthenticationManager.class); - Converter> jwtAuthConverter = (Converter>) mock(Converter.class); + Converter> jwtAuthConverter = (Converter>) mock( + Converter.class); JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( (issuer) -> Mono.just(authenticationManager), jwtAuthConverter); MockServerWebExchange exchange = withBearerToken(this.jwt); @@ -211,10 +214,10 @@ public void constructorWhenNullAuthenticationManagerResolverThenException() { @Test public void constructWhenNullIssuerConverterThenException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new JwtIssuerReactiveAuthenticationManagerResolver( - context -> Mono.just(new JwtReactiveAuthenticationManager( - ReactiveJwtDecoders.fromIssuerLocation("trusted"))), null)); + assertThatIllegalArgumentException().isThrownBy(() -> new JwtIssuerReactiveAuthenticationManagerResolver( + context -> Mono + .just(new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation("trusted"))), + null)); } private String jwt(String claim, String value) { From 86c51b298b21dc47e177281233b95537e073d5ea Mon Sep 17 00:00:00 2001 From: Krzysztof P Date: Tue, 6 Oct 2020 13:54:59 +0200 Subject: [PATCH 4/4] Removal of JwtIssuerAuthenticationManagerResolver customization - separate ticket needed + setter instead of constructor --- ...wtIssuerAuthenticationManagerResolver.java | 32 ++++-------- ...ReactiveAuthenticationManagerResolver.java | 50 +++++++------------ ...uerAuthenticationManagerResolverTests.java | 26 ---------- ...iveAuthenticationManagerResolverTests.java | 32 ++---------- 4 files changed, 32 insertions(+), 108 deletions(-) diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java index c5ce1fc95a1..eb21703fc2d 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java @@ -65,7 +65,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat private final AuthenticationManagerResolver issuerAuthenticationManagerResolver; - private final Converter issuerConverter; + private Converter issuerConverter; /** * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided @@ -78,6 +78,7 @@ public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) { /** * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided + * * parameters * @param trustedIssuers a list of trusted issuers */ @@ -88,26 +89,6 @@ public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers) this.issuerConverter = new JwtClaimIssuerConverter(); } - /** - * Construct a {@link JwtIssuerAuthenticationManagerResolver} with a custom - * {@link JwtAuthenticationConverter} using the provided parameters - * - * A custom {@link JwtAuthenticationConverter} allows to use a custom - * {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) to handle an - * untypical JWT token - * @param trustedIssuers a list of trusted issuers - * @param jwtAuthenticationConverter a custom {@link JwtAuthenticationConverter} - * @since 5.4 - */ - public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers, - JwtAuthenticationConverter jwtAuthenticationConverter) { - Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); - Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); - this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( - Collections.unmodifiableCollection(trustedIssuers)::contains, jwtAuthenticationConverter); - this.issuerConverter = new JwtClaimIssuerConverter(); - } - /** * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided * parameters @@ -184,6 +165,10 @@ public AuthenticationManager resolve(HttpServletRequest request) { return authenticationManager; } + public void setIssuerConverter(Converter issuerConverter) { + this.issuerConverter = issuerConverter; + } + private static class JwtClaimIssuerConverter implements Converter { private final BearerTokenResolver resolver = new DefaultBearerTokenResolver(); @@ -233,11 +218,12 @@ public AuthenticationManager resolve(String issuer) { (k) -> { this.logger.debug("Constructing AuthenticationManager"); JwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuer); - if (jwtAuthenticationConverter != null) { + if (this.jwtAuthenticationConverter != null) { this.logger.debug(("Using custom JwtAuthenticationConverter")); final JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider( jwtDecoder); - jwtAuthenticationProvider.setJwtAuthenticationConverter(jwtAuthenticationConverter); + jwtAuthenticationProvider + .setJwtAuthenticationConverter(this.jwtAuthenticationConverter); return jwtAuthenticationProvider::authenticate; } else { diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java index be5177767ae..239e21ff5a5 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java @@ -65,7 +65,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver private final ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver; - private final Converter> issuerConverter; + private Converter> issuerConverter; /** * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the @@ -88,25 +88,6 @@ public JwtIssuerReactiveAuthenticationManagerResolver(Collection trusted this.issuerConverter = new JwtClaimIssuerConverter(); } - /** - * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the - * provided parameters - * - * A custom {@link ReactiveJwtAuthenticationConverterAdapter} allows to use a custom - * {@link Converter} (much like {@link JwtGrantedAuthoritiesConverter}) to handle an - * untypical JWT token - * @param trustedIssuers a collection of trusted issuers - * @param reactiveJwtAuthenticationConverterAdapter a custom - * {@link ReactiveJwtAuthenticationConverterAdapter} - */ - public JwtIssuerReactiveAuthenticationManagerResolver(Collection trustedIssuers, - ReactiveJwtAuthenticationConverterAdapter reactiveJwtAuthenticationConverterAdapter) { - Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); - this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( - new ArrayList<>(trustedIssuers)::contains, reactiveJwtAuthenticationConverterAdapter); - this.issuerConverter = new JwtClaimIssuerConverter(); - } - /** * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the * provided parameters @@ -182,6 +163,10 @@ public Mono resolve(ServerWebExchange exchange) { // @formatter:on } + public void setIssuerConverter(Converter> issuerConverter) { + this.issuerConverter = issuerConverter; + } + private static class JwtClaimIssuerConverter implements Converter> { private final ServerBearerTokenAuthenticationConverter converter = new ServerBearerTokenAuthenticationConverter(); @@ -231,18 +216,19 @@ public Mono resolve(String issuer) { } // @formatter:off return this.authenticationManagers.computeIfAbsent(issuer, - (k) -> Mono.fromCallable(() -> { - if(jwtAuthenticationConverterAdapter != null) { - final JwtReactiveAuthenticationManager authenticationManager = - new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); - authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverterAdapter); - return authenticationManager; - } else { - return new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); - } - }) - .subscribeOn(Schedulers.boundedElastic()) - .cache() + (k) -> Mono.fromCallable(() -> { + if (this.jwtAuthenticationConverterAdapter != null) { + final JwtReactiveAuthenticationManager authenticationManager = + new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); + authenticationManager.setJwtAuthenticationConverter(this.jwtAuthenticationConverterAdapter); + return authenticationManager; + } + else { + return new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .cache() ); // @formatter:on } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java index 1aac9e03ca3..73689179db3 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java @@ -88,32 +88,6 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } } - @Test - public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() - throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.start(); - String issuer = server.url("").toString(); - // @formatter:off - server.enqueue(new MockResponse().setResponseCode(200) - .setHeader("Content-Type", "application/json") - .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer) - )); - // @formatter:on - JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), - new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); - jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( - Collections.singletonList(issuer), new JwtAuthenticationConverter()); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader("Authorization", "Bearer " + jws.serialize()); - AuthenticationManager authenticationManager = authenticationManagerResolver.resolve(request); - assertThat(authenticationManager).isNotNull(); - AuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(request); - assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); - } - } - @Test public void resolveWhenUsingUntrustedIssuerThenException() { JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java index 001ddeb0a0d..c5e40fcbbeb 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java @@ -32,9 +32,6 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.junit.Test; -import org.springframework.core.convert.converter.Converter; -import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders; -import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; @@ -45,6 +42,10 @@ import org.springframework.security.oauth2.jose.TestKeys; import org.springframework.security.oauth2.jwt.JwtClaimNames; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders; +import org.springframework.web.server.ServerWebExchange; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -89,29 +90,6 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro } } - @Test - public void resolveWhenUsingTrustedIssuerAndCustomJwtAuthConverterThenReturnsAuthenticationManager() - throws Exception { - try (MockWebServer server = new MockWebServer()) { - String issuer = server.url("").toString(); - server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json") - .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); - JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), - new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer)))); - jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( - Collections.singletonList(issuer), - new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter())); - MockServerWebExchange exchange = withBearerToken(jws.serialize()); - ReactiveAuthenticationManager authenticationManager = authenticationManagerResolver.resolve(exchange) - .block(); - assertThat(authenticationManager).isNotNull(); - ReactiveAuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(exchange) - .block(); - assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); - } - } - @Test public void resolveWhenUsingUntrustedIssuerThenException() { JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( @@ -215,7 +193,7 @@ public void constructorWhenNullAuthenticationManagerResolverThenException() { @Test public void constructWhenNullIssuerConverterThenException() { assertThatIllegalArgumentException().isThrownBy(() -> new JwtIssuerReactiveAuthenticationManagerResolver( - context -> Mono + (context) -> Mono .just(new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation("trusted"))), null)); }