Skip to content

Commit de672e3

Browse files
committed
Polish oauth2ResourceServer() Error Messaging
Fixes: gh-6876
1 parent 1fc5b27 commit de672e3

File tree

4 files changed

+93
-24
lines changed

4 files changed

+93
-24
lines changed

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

+22-13
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,7 @@ public void configure(H http) throws Exception {
232232
BearerTokenResolver bearerTokenResolver = getBearerTokenResolver();
233233
this.requestMatcher.setBearerTokenResolver(bearerTokenResolver);
234234

235-
if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) {
236-
throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
237-
"same time");
238-
}
239-
240-
if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null &&
241-
this.authenticationManagerResolver == null ) {
242-
243-
throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
244-
"in Spring Security and neither was found. Make sure to configure JWT " +
245-
"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
246-
"http.oauth2ResourceServer().opaque().");
247-
}
235+
validateConfiguration();
248236

249237
AuthenticationManagerResolver resolver = this.authenticationManagerResolver;
250238
if (resolver == null) {
@@ -260,6 +248,27 @@ public void configure(H http) throws Exception {
260248
http.addFilter(filter);
261249
}
262250

251+
private void validateConfiguration() {
252+
if (this.authenticationManagerResolver == null) {
253+
if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null) {
254+
throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
255+
"in Spring Security and neither was found. Make sure to configure JWT " +
256+
"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
257+
"http.oauth2ResourceServer().opaqueToken().");
258+
}
259+
260+
if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) {
261+
throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
262+
"same time.");
263+
}
264+
} else {
265+
if (this.jwtConfigurer != null || this.opaqueTokenConfigurer != null) {
266+
throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " +
267+
"precedence over any jwt() or opaqueToken() configuration.");
268+
}
269+
}
270+
}
271+
263272
public class JwtConfigurer {
264273
private final ApplicationContext context;
265274

config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

+22-11
Original file line numberDiff line numberDiff line change
@@ -1622,17 +1622,7 @@ protected void configure(ServerHttpSecurity http) {
16221622
registerDefaultAuthenticationEntryPoint(http);
16231623
registerDefaultCsrfOverride(http);
16241624

1625-
if (this.jwt != null && this.opaqueToken != null) {
1626-
throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
1627-
"same time");
1628-
}
1629-
1630-
if (this.jwt == null && this.opaqueToken == null && this.authenticationManagerResolver == null) {
1631-
throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
1632-
"in Spring Security and neither was found. Make sure to configure JWT " +
1633-
"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
1634-
"http.oauth2ResourceServer().opaqueToken().");
1635-
}
1625+
validateConfiguration();
16361626

16371627
if (this.authenticationManagerResolver != null) {
16381628
AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.authenticationManagerResolver);
@@ -1646,6 +1636,27 @@ protected void configure(ServerHttpSecurity http) {
16461636
}
16471637
}
16481638

1639+
private void validateConfiguration() {
1640+
if (this.authenticationManagerResolver == null) {
1641+
if (this.jwt == null && this.opaqueToken == null) {
1642+
throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " +
1643+
"in Spring Security and neither was found. Make sure to configure JWT " +
1644+
"via http.oauth2ResourceServer().jwt() or Opaque Tokens via " +
1645+
"http.oauth2ResourceServer().opaqueToken().");
1646+
}
1647+
1648+
if (this.jwt != null && this.opaqueToken != null) {
1649+
throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " +
1650+
"same time.");
1651+
}
1652+
} else {
1653+
if (this.jwt != null || this.opaqueToken != null) {
1654+
throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " +
1655+
"precedence over any jwt() or opaqueToken() configuration.");
1656+
}
1657+
}
1658+
}
1659+
16491660
private void registerDefaultAccessDeniedHandler(ServerHttpSecurity http) {
16501661
if ( http.exceptionHandling != null ) {
16511662
http.defaultAccessDeniedHandlers.add(

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

+23
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import org.springframework.security.access.prepost.PreAuthorize;
6666
import org.springframework.security.authentication.AbstractAuthenticationToken;
6767
import org.springframework.security.authentication.AuthenticationManager;
68+
import org.springframework.security.authentication.AuthenticationManagerResolver;
6869
import org.springframework.security.authentication.AuthenticationProvider;
6970
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
7071
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
@@ -1358,6 +1359,13 @@ public void configureWhenUsingBothJwtAndOpaqueThenWiringException() {
13581359
.hasMessageContaining("Spring Security only supports JWTs or Opaque Tokens");
13591360
}
13601361

1362+
@Test
1363+
public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() {
1364+
assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire())
1365+
.isInstanceOf(BeanCreationException.class)
1366+
.hasMessageContaining("authenticationManagerResolver");
1367+
}
1368+
13611369
// -- support
13621370

13631371
@EnableWebSecurity
@@ -2064,6 +2072,21 @@ protected void configure(HttpSecurity http) throws Exception {
20642072
}
20652073
}
20662074

2075+
@EnableWebSecurity
2076+
static class AuthenticationManagerResolverPlusOtherConfig extends WebSecurityConfigurerAdapter {
2077+
@Override
2078+
protected void configure(HttpSecurity http) throws Exception {
2079+
// @formatter:off
2080+
http
2081+
.authorizeRequests()
2082+
.anyRequest().authenticated()
2083+
.and()
2084+
.oauth2ResourceServer()
2085+
.authenticationManagerResolver(mock(AuthenticationManagerResolver.class))
2086+
.opaqueToken();
2087+
}
2088+
}
2089+
20672090
@Configuration
20682091
static class JwtDecoderConfig {
20692092
@Bean

config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java

+26
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.junit.runner.RunWith;
4242
import reactor.core.publisher.Mono;
4343

44+
import org.springframework.beans.factory.BeanCreationException;
4445
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
4546
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
4647
import org.springframework.beans.factory.annotation.Autowired;
@@ -457,6 +458,13 @@ public void introspectWhenValidAndIntrospectionInLambdaThenReturnsOk() {
457458
.expectStatus().isOk();
458459
}
459460

461+
@Test
462+
public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() {
463+
assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire())
464+
.isInstanceOf(BeanCreationException.class)
465+
.hasMessageContaining("authenticationManagerResolver");
466+
}
467+
460468
@EnableWebFlux
461469
@EnableWebFluxSecurity
462470
static class PublicKeyConfig {
@@ -849,6 +857,24 @@ void shutdown() throws IOException {
849857
}
850858
}
851859

860+
@EnableWebFlux
861+
@EnableWebFluxSecurity
862+
static class AuthenticationManagerResolverPlusOtherConfig {
863+
@Bean
864+
SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
865+
// @formatter:off
866+
http
867+
.authorizeExchange()
868+
.anyExchange().authenticated()
869+
.and()
870+
.oauth2ResourceServer()
871+
.authenticationManagerResolver(mock(ReactiveAuthenticationManagerResolver.class))
872+
.opaqueToken();
873+
874+
return http.build();
875+
}
876+
}
877+
852878
@RestController
853879
static class RootController {
854880
@GetMapping

0 commit comments

Comments
 (0)