Browse Source

Allow authenticationManagerResolver to take precedence over jwt/opaqueToken

When OAuth2ResourceServerConfigurer.authenticationManagerResolver() is
configured, it now takes precedence over any jwt() or opaqueToken()
configuration without throwing an exception. This follows Spring
Security's convention where specialized configurations take precedence
over general ones at runtime.

The solution removes the validation check that prevented
authenticationManagerResolver from being used with jwt/opaqueToken
configurations, allowing for more flexible configuration scenarios such
as those needed by Spring Authorization Server when supporting both JWT
and opaque tokens.

Closes gh-16406

Signed-off-by: academey <academey@gmail.com>
pull/17676/head
academey 4 months ago
parent
commit
9c45ace88e
  1. 11
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java
  2. 49
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java

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

@ -256,8 +256,11 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder< @@ -256,8 +256,11 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
@Override
public void configure(H http) {
// Use the authenticationManagerResolver if configured, as it takes precedence
// over any jwt() or opaqueToken() configuration
AuthenticationManagerResolver resolver = this.authenticationManagerResolver;
if (resolver == null) {
// Fall back to jwt() or opaqueToken() configuration
AuthenticationManager authenticationManager = getAuthenticationManager(http);
resolver = (request) -> authenticationManager;
}
@ -282,11 +285,9 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder< @@ -282,11 +285,9 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
Assert.state(this.jwtConfigurer == null || this.opaqueTokenConfigurer == null,
"Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time.");
}
else {
Assert.state(this.jwtConfigurer == null && this.opaqueTokenConfigurer == null,
"If an authenticationManagerResolver() is configured, then it takes "
+ "precedence over any jwt() or opaqueToken() configuration.");
}
// When authenticationManagerResolver is configured, it takes precedence over
// jwt() or opaqueToken()
// configuration, so no validation is needed for that case
}
private void registerDefaultAccessDeniedHandler(H http) {

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

@ -1339,10 +1339,18 @@ public class OAuth2ResourceServerConfigurerTests { @@ -1339,10 +1339,18 @@ public class OAuth2ResourceServerConfigurerTests {
}
@Test
public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() {
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire())
.withMessageContaining("authenticationManagerResolver");
public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenAuthenticationManagerResolverTakesPrecedence() {
// authenticationManagerResolver should take precedence over opaqueToken
// configuration
this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire();
// No exception should be thrown
}
@Test
public void configureWhenUsingBothAuthenticationManagerResolverAndJwtThenAuthenticationManagerResolverTakesPrecedence() {
// authenticationManagerResolver should take precedence over jwt configuration
this.spring.register(AuthenticationManagerResolverPlusJwtConfig.class).autowire();
// No exception should be thrown
}
@Test
@ -2601,6 +2609,11 @@ public class OAuth2ResourceServerConfigurerTests { @@ -2601,6 +2609,11 @@ public class OAuth2ResourceServerConfigurerTests {
@EnableWebSecurity
static class AuthenticationManagerResolverPlusOtherConfig {
@Bean
OpaqueTokenIntrospector opaqueTokenIntrospector() {
return mock(OpaqueTokenIntrospector.class);
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
@ -2608,8 +2621,8 @@ public class OAuth2ResourceServerConfigurerTests { @@ -2608,8 +2621,8 @@ public class OAuth2ResourceServerConfigurerTests {
.authorizeHttpRequests((requests) -> requests
.anyRequest().authenticated())
.oauth2ResourceServer((server) -> server
.authenticationManagerResolver(mock(AuthenticationManagerResolver.class))
.opaqueToken(Customizer.withDefaults()));
.opaqueToken(Customizer.withDefaults())
.authenticationManagerResolver(mock(AuthenticationManagerResolver.class)));
return http.build();
// @formatter:on
}
@ -2788,4 +2801,28 @@ public class OAuth2ResourceServerConfigurerTests { @@ -2788,4 +2801,28 @@ public class OAuth2ResourceServerConfigurerTests {
}
@Configuration
@EnableWebSecurity
static class AuthenticationManagerResolverPlusJwtConfig {
@Bean
JwtDecoder jwtDecoder() {
return mock(JwtDecoder.class);
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeHttpRequests((requests) -> requests
.anyRequest().authenticated())
.oauth2ResourceServer((server) -> server
.jwt(Customizer.withDefaults())
.authenticationManagerResolver(mock(AuthenticationManagerResolver.class)));
return http.build();
// @formatter:on
}
}
}

Loading…
Cancel
Save