2
0
Эх сурвалжийг харах

Allow Customization of Bearer Token Resolution

Closes gh-8535
Arvid Ottenberg 4 жил өмнө
parent
commit
d0d655e18d

+ 21 - 2
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<String> issuerAuthenticationManagerResolver;
 
-	private final Converter<HttpServletRequest, String> issuerConverter = new JwtClaimIssuerConverter();
+	private Converter<HttpServletRequest, String> issuerConverter = new JwtClaimIssuerConverter();
 
 	/**
 	 * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided
@@ -130,9 +130,28 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
 		return authenticationManager;
 	}
 
+	/**
+	 * Set a custom bearer token resolver
+	 *
+	 * @since 5.5
+	 */
+	public void setBearerTokenResolver(BearerTokenResolver bearerTokenResolver) {
+		Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null");
+		this.issuerConverter = new JwtClaimIssuerConverter(bearerTokenResolver);
+	}
+
 	private static class JwtClaimIssuerConverter implements Converter<HttpServletRequest, String> {
 
-		private final BearerTokenResolver resolver = new DefaultBearerTokenResolver();
+		private final BearerTokenResolver resolver;
+
+		JwtClaimIssuerConverter() {
+			this(new DefaultBearerTokenResolver());
+		}
+
+		JwtClaimIssuerConverter(BearerTokenResolver bearerTokenResolver) {
+			Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null");
+			this.resolver = bearerTokenResolver;
+		}
 
 		@Override
 		public String convert(@NonNull HttpServletRequest request) {

+ 24 - 2
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<String> issuerAuthenticationManagerResolver;
 
-	private final Converter<ServerWebExchange, Mono<String>> issuerConverter = new JwtClaimIssuerConverter();
+	private Converter<ServerWebExchange, Mono<String>> issuerConverter = new JwtClaimIssuerConverter();
 
 	/**
 	 * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the
@@ -131,9 +131,31 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
 		// @formatter:on
 	}
 
+	/**
+	 * Set a custom server bearer token authentication converter
+	 *
+	 * @since 5.5
+	 */
+	public void setServerBearerTokenAuthenticationConverter(
+			ServerBearerTokenAuthenticationConverter serverBearerTokenAuthenticationConverter) {
+		Assert.notNull(serverBearerTokenAuthenticationConverter,
+				"serverBearerTokenAuthenticationConverter cannot be null");
+		this.issuerConverter = new JwtClaimIssuerConverter(serverBearerTokenAuthenticationConverter);
+	}
+
 	private static class JwtClaimIssuerConverter implements Converter<ServerWebExchange, Mono<String>> {
 
-		private final ServerBearerTokenAuthenticationConverter converter = new ServerBearerTokenAuthenticationConverter();
+		private final ServerBearerTokenAuthenticationConverter converter;
+
+		JwtClaimIssuerConverter() {
+			this(new ServerBearerTokenAuthenticationConverter());
+		}
+
+		JwtClaimIssuerConverter(ServerBearerTokenAuthenticationConverter serverBearerTokenAuthenticationConverter) {
+			Assert.notNull(serverBearerTokenAuthenticationConverter,
+					"serverBearerTokenAuthenticationConverter cannot be null");
+			this.converter = serverBearerTokenAuthenticationConverter;
+		}
 
 		@Override
 		public Mono<String> convert(@NonNull ServerWebExchange exchange) {

+ 28 - 0
oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java

@@ -21,6 +21,8 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
 import com.nimbusds.jose.JWSObject;
@@ -39,11 +41,15 @@ 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.server.resource.web.BearerTokenResolver;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 /**
  * Tests for {@link JwtIssuerAuthenticationManagerResolver}
@@ -113,6 +119,19 @@ public class JwtIssuerAuthenticationManagerResolverTests {
 		assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager);
 	}
 
+	@Test
+	public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomBearerTokenResolverThenUses() {
+		AuthenticationManager authenticationManager = mock(AuthenticationManager.class);
+		JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver(
+				(issuer) -> authenticationManager);
+		BearerTokenResolver bearerTokenResolverSpy = spy(new TestBearerTokenResolver());
+		authenticationManagerResolver.setBearerTokenResolver(bearerTokenResolverSpy);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.addHeader("Authorization", "Bearer " + this.jwt);
+		assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager);
+		verify(bearerTokenResolverSpy).resolve(any());
+	}
+
 	@Test
 	public void resolveWhenUsingExternalSourceThenRespondsToChanges() {
 		MockHttpServletRequest request = new MockHttpServletRequest();
@@ -196,4 +215,13 @@ public class JwtIssuerAuthenticationManagerResolverTests {
 		return jwt.serialize();
 	}
 
+	static class TestBearerTokenResolver implements BearerTokenResolver {
+
+		@Override
+		public String resolve(HttpServletRequest request) {
+			return "eyJhbGciOiJub25lIn0.eyJpc3MiOiJ0cnVzdGVkIn0.";
+		}
+
+	}
+
 }

+ 18 - 0
oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java

@@ -41,11 +41,15 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager
 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.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 /**
  * Tests for {@link JwtIssuerReactiveAuthenticationManagerResolver}
@@ -111,6 +115,20 @@ public class JwtIssuerReactiveAuthenticationManagerResolverTests {
 		assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager);
 	}
 
+	@Test
+	public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverAndCustomServerBearerTokenAuthenticationConverterThenUses() {
+		ReactiveAuthenticationManager authenticationManager = mock(ReactiveAuthenticationManager.class);
+		JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver(
+				(issuer) -> Mono.just(authenticationManager));
+		ServerBearerTokenAuthenticationConverter serverBearerTokenAuthenticationConverterSpy = spy(
+				new ServerBearerTokenAuthenticationConverter());
+		authenticationManagerResolver
+				.setServerBearerTokenAuthenticationConverter(serverBearerTokenAuthenticationConverterSpy);
+		MockServerWebExchange exchange = withBearerToken(this.jwt);
+		assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager);
+		verify(serverBearerTokenAuthenticationConverterSpy).convert(any());
+	}
+
 	@Test
 	public void resolveWhenUsingExternalSourceThenRespondsToChanges() {
 		MockServerWebExchange exchange = withBearerToken(this.jwt);