소스 검색

Polish oauth2ResourceServer() Error Messaging

Fixes: gh-6876
Josh Cummings 6 년 전
부모
커밋
de672e3ae9

+ 22 - 13
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java

@@ -232,19 +232,7 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
 		BearerTokenResolver bearerTokenResolver = getBearerTokenResolver();
 		this.requestMatcher.setBearerTokenResolver(bearerTokenResolver);
 
-		if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) {
-			throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
-					"same time");
-		}
-
-		if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null &&
-				this.authenticationManagerResolver == null ) {
-
-			throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
-					"in Spring Security and neither was found. Make sure to configure JWT " +
-					"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
-					"http.oauth2ResourceServer().opaque().");
-		}
+		validateConfiguration();
 
 		AuthenticationManagerResolver resolver = this.authenticationManagerResolver;
 		if (resolver == null) {
@@ -260,6 +248,27 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
 		http.addFilter(filter);
 	}
 
+	private void validateConfiguration() {
+		if (this.authenticationManagerResolver == null) {
+			if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null) {
+				throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
+						"in Spring Security and neither was found. Make sure to configure JWT " +
+						"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
+						"http.oauth2ResourceServer().opaqueToken().");
+			}
+
+			if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) {
+				throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
+						"same time.");
+			}
+		} else {
+			if (this.jwtConfigurer != null || this.opaqueTokenConfigurer != null) {
+				throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " +
+						"precedence over any jwt() or opaqueToken() configuration.");
+			}
+		}
+	}
+
 	public class JwtConfigurer {
 		private final ApplicationContext context;
 

+ 22 - 11
config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

@@ -1622,17 +1622,7 @@ public class ServerHttpSecurity {
 			registerDefaultAuthenticationEntryPoint(http);
 			registerDefaultCsrfOverride(http);
 
-			if (this.jwt != null && this.opaqueToken != null) {
-				throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
-						"same time");
-			}
-
-			if (this.jwt == null && this.opaqueToken == null && this.authenticationManagerResolver == null) {
-				throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
-						"in Spring Security and neither was found. Make sure to configure JWT " +
-						"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
-						"http.oauth2ResourceServer().opaqueToken().");
-			}
+			validateConfiguration();
 
 			if (this.authenticationManagerResolver != null) {
 				AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.authenticationManagerResolver);
@@ -1646,6 +1636,27 @@ public class ServerHttpSecurity {
 			}
 		}
 
+		private void validateConfiguration() {
+			if (this.authenticationManagerResolver == null) {
+				if (this.jwt == null && this.opaqueToken == null) {
+					throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
+							"in Spring Security and neither was found. Make sure to configure JWT " +
+							"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
+							"http.oauth2ResourceServer().opaqueToken().");
+				}
+
+				if (this.jwt != null && this.opaqueToken != null) {
+					throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
+							"same time.");
+				}
+			} else {
+				if (this.jwt != null || this.opaqueToken != null) {
+					throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " +
+							"precedence over any jwt() or opaqueToken() configuration.");
+				}
+			}
+		}
+
 		private void registerDefaultAccessDeniedHandler(ServerHttpSecurity http) {
 			if ( http.exceptionHandling != null ) {
 				http.defaultAccessDeniedHandlers.add(

+ 23 - 0
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java

@@ -65,6 +65,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationManagerResolver;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
@@ -1358,6 +1359,13 @@ public class OAuth2ResourceServerConfigurerTests {
 				.hasMessageContaining("Spring Security only supports JWTs or Opaque Tokens");
 	}
 
+	@Test
+	public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() {
+		assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class)
+				.hasMessageContaining("authenticationManagerResolver");
+	}
+
 	// -- support
 
 	@EnableWebSecurity
@@ -2064,6 +2072,21 @@ public class OAuth2ResourceServerConfigurerTests {
 		}
 	}
 
+	@EnableWebSecurity
+	static class AuthenticationManagerResolverPlusOtherConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.oauth2ResourceServer()
+					.authenticationManagerResolver(mock(AuthenticationManagerResolver.class))
+					.opaqueToken();
+		}
+	}
+
 	@Configuration
 	static class JwtDecoderConfig {
 		@Bean

+ 26 - 0
config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java

@@ -41,6 +41,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import reactor.core.publisher.Mono;
 
+import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -457,6 +458,13 @@ public class OAuth2ResourceServerSpecTests {
 				.expectStatus().isOk();
 	}
 
+	@Test
+	public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() {
+		assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class)
+				.hasMessageContaining("authenticationManagerResolver");
+	}
+
 	@EnableWebFlux
 	@EnableWebFluxSecurity
 	static class PublicKeyConfig {
@@ -849,6 +857,24 @@ public class OAuth2ResourceServerSpecTests {
 		}
 	}
 
+	@EnableWebFlux
+	@EnableWebFluxSecurity
+	static class AuthenticationManagerResolverPlusOtherConfig {
+		@Bean
+		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.authorizeExchange()
+					.anyExchange().authenticated()
+					.and()
+				.oauth2ResourceServer()
+					.authenticationManagerResolver(mock(ReactiveAuthenticationManagerResolver.class))
+					.opaqueToken();
+
+			return http.build();
+		}
+	}
+
 	@RestController
 	static class RootController {
 		@GetMapping