Skip to content

Commit 7ded671

Browse files
committed
Refactor AuthenticationDetailsSource support
- BearerTokenAuthenticationFilter exposes this directly, simplifying configuration and removing a package tangle Closes gh-9576
1 parent 21f9876 commit 7ded671

File tree

6 files changed

+78
-301
lines changed

6 files changed

+78
-301
lines changed

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

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import org.springframework.security.oauth2.jwt.Jwt;
4040
import org.springframework.security.oauth2.jwt.JwtDecoder;
4141
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
42-
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationConverter;
4342
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
4443
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider;
4544
import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider;
@@ -52,7 +51,6 @@
5251
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
5352
import org.springframework.security.web.AuthenticationEntryPoint;
5453
import org.springframework.security.web.access.AccessDeniedHandler;
55-
import org.springframework.security.web.authentication.AuthenticationConverter;
5654
import org.springframework.security.web.util.matcher.AndRequestMatcher;
5755
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
5856
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
@@ -80,8 +78,6 @@
8078
* authentication failures are handled
8179
* <li>{@link #bearerTokenResolver(BearerTokenResolver)} - customizes how to resolve a
8280
* bearer token from the request</li>
83-
* <li>{@link #authenticationConverter(AuthenticationConverter)}</li> - customizes how to
84-
* convert a bearer token authentication from the request
8581
* <li>{@link #jwt(Customizer)} - enables Jwt-encoded bearer token support</li>
8682
* <li>{@link #opaqueToken(Customizer)} - enables opaque bearer token support</li>
8783
* </ul>
@@ -163,8 +159,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
163159

164160
private BearerTokenRequestMatcher requestMatcher = new BearerTokenRequestMatcher();
165161

166-
private AuthenticationConverter authenticationConverter;
167-
168162
public OAuth2ResourceServerConfigurer(ApplicationContext context) {
169163
Assert.notNull(context, "context cannot be null");
170164
this.context = context;
@@ -195,12 +189,6 @@ public OAuth2ResourceServerConfigurer<H> bearerTokenResolver(BearerTokenResolver
195189
return this;
196190
}
197191

198-
public OAuth2ResourceServerConfigurer<H> authenticationConverter(AuthenticationConverter authenticationConverter) {
199-
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
200-
this.authenticationConverter = authenticationConverter;
201-
return this;
202-
}
203-
204192
public JwtConfigurer jwt() {
205193
if (this.jwtConfigurer == null) {
206194
this.jwtConfigurer = new JwtConfigurer(this.context);
@@ -265,10 +253,8 @@ public void configure(H http) {
265253
resolver = (request) -> authenticationManager;
266254
}
267255

268-
this.authenticationConverter = getAuthenticationConverter();
269-
270256
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver);
271-
filter.setAuthenticationConverter(this.authenticationConverter);
257+
filter.setBearerTokenResolver(bearerTokenResolver);
272258
filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
273259
filter = postProcess(filter);
274260
http.addFilter(filter);
@@ -362,20 +348,6 @@ BearerTokenResolver getBearerTokenResolver() {
362348
return this.bearerTokenResolver;
363349
}
364350

365-
AuthenticationConverter getAuthenticationConverter() {
366-
if (this.authenticationConverter == null) {
367-
if (this.context.getBeanNamesForType(BearerTokenAuthenticationConverter.class).length > 0) {
368-
this.authenticationConverter = this.context.getBean(BearerTokenAuthenticationConverter.class);
369-
}
370-
else {
371-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
372-
converter.setBearerTokenResolver(getBearerTokenResolver());
373-
this.authenticationConverter = converter;
374-
}
375-
}
376-
return this.authenticationConverter;
377-
}
378-
379351
public class JwtConfigurer {
380352

381353
private final ApplicationContext context;

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

Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@
7575
import org.springframework.mock.web.MockHttpServletRequest;
7676
import org.springframework.security.access.prepost.PreAuthorize;
7777
import org.springframework.security.authentication.AbstractAuthenticationToken;
78+
import org.springframework.security.authentication.AuthenticationDetailsSource;
7879
import org.springframework.security.authentication.AuthenticationEventPublisher;
7980
import org.springframework.security.authentication.AuthenticationManager;
8081
import org.springframework.security.authentication.AuthenticationManagerResolver;
8182
import org.springframework.security.authentication.AuthenticationProvider;
8283
import org.springframework.security.authentication.AuthenticationServiceException;
84+
import org.springframework.security.config.annotation.ObjectPostProcessor;
8385
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
8486
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
8587
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -109,20 +111,20 @@
109111
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
110112
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
111113
import org.springframework.security.oauth2.jwt.TestJwts;
112-
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
113114
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
114-
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationConverter;
115115
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
116116
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
117117
import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver;
118118
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
119119
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
120120
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
121+
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
121122
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
122123
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
123124
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
124125
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
125126
import org.springframework.security.web.AuthenticationEntryPoint;
127+
import org.springframework.security.web.SecurityFilterChain;
126128
import org.springframework.security.web.access.AccessDeniedHandler;
127129
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
128130
import org.springframework.test.web.servlet.MockMvc;
@@ -724,68 +726,14 @@ public void getBearerTokenResolverWhenNoResolverSpecifiedThenTheDefaultIsUsed()
724726
}
725727

726728
@Test
727-
public void getBearerTokenAuthenticationConverterWhenDuplicateConverterBeansAndAnotherOnTheDslThenTheDslOneIsUsed() {
728-
BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter();
729-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
730-
GenericWebApplicationContext context = new GenericWebApplicationContext();
731-
context.registerBean("converterOne", BearerTokenAuthenticationConverter.class, () -> converterBean);
732-
context.registerBean("converterTwo", BearerTokenAuthenticationConverter.class, () -> converterBean);
733-
this.spring.context(context).autowire();
734-
OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context);
735-
oauth2.authenticationConverter(converter);
736-
assertThat(oauth2.getAuthenticationConverter()).isEqualTo(converter);
737-
}
738-
739-
@Test
740-
public void getBearerTokenAuthenticationConverterWhenDuplicateConverterBeansThenWiringException() {
741-
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> this.spring
742-
.register(MultipleBearerTokenAuthenticationConverterBeansConfig.class, JwtDecoderConfig.class)
743-
.autowire()).withRootCauseInstanceOf(NoUniqueBeanDefinitionException.class);
744-
}
745-
746-
@Test
747-
public void getBearerTokenAuthenticationConverterWhenConverterBeanAndAnotherOnTheDslThenTheDslOneIsUsed() {
748-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
749-
BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter();
750-
GenericWebApplicationContext context = new GenericWebApplicationContext();
751-
context.registerBean(BearerTokenAuthenticationConverter.class, () -> converterBean);
752-
this.spring.context(context).autowire();
753-
OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context);
754-
oauth2.authenticationConverter(converter);
755-
assertThat(oauth2.getAuthenticationConverter()).isEqualTo(converter);
756-
}
757-
758-
@Test
759-
public void getBearerTokenAuthenticationConverterWhenNoConverterSpecifiedThenTheDefaultIsUsed() {
760-
ApplicationContext context = this.spring.context(new GenericWebApplicationContext()).getContext();
761-
OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context);
762-
assertThat(oauth2.getAuthenticationConverter()).isInstanceOf(BearerTokenAuthenticationConverter.class);
763-
}
764-
765-
@Test
766-
public void getBearerTokenAuthenticationConverterWhenConverterBeanRegisteredThenBeanIsUsed() {
767-
BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter();
768-
GenericWebApplicationContext context = new GenericWebApplicationContext();
769-
context.registerBean(BearerTokenAuthenticationConverter.class, () -> converterBean);
770-
this.spring.context(context).autowire();
771-
OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context);
772-
assertThat(oauth2.getAuthenticationConverter()).isEqualTo(converterBean);
773-
774-
}
775-
776-
@Test
777-
public void getBearerTokenAuthenticationConverterWhenOnlyResolverBeanRegisteredThenUseTheResolver() {
778-
HttpServletRequest servletRequest = mock(HttpServletRequest.class);
779-
BearerTokenResolver resolverBean = (request) -> "bearer customToken";
780-
GenericWebApplicationContext context = new GenericWebApplicationContext();
781-
context.registerBean(BearerTokenResolver.class, () -> resolverBean);
782-
this.spring.context(context).autowire();
783-
OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context);
784-
BearerTokenAuthenticationToken bearerTokenAuthenticationToken = (BearerTokenAuthenticationToken) oauth2
785-
.getAuthenticationConverter().convert(servletRequest);
786-
String token = bearerTokenAuthenticationToken.getToken();
787-
assertThat(token).isEqualTo("bearer customToken");
788-
729+
public void requestWhenCustomAuthenticationDetailsSourceThenUsed() throws Exception {
730+
this.spring.register(CustomAuthenticationDetailsSource.class, JwtDecoderConfig.class, BasicController.class)
731+
.autowire();
732+
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
733+
given(decoder.decode(anyString())).willReturn(JWT);
734+
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
735+
.andExpect(content().string(JWT_SUBJECT));
736+
verifyBean(AuthenticationDetailsSource.class).buildDetails(any());
789737
}
790738

791739
@Test
@@ -1940,29 +1888,35 @@ BearerTokenResolver resolverTwo() {
19401888
}
19411889

19421890
@EnableWebSecurity
1943-
static class MultipleBearerTokenAuthenticationConverterBeansConfig extends WebSecurityConfigurerAdapter {
1891+
static class CustomAuthenticationDetailsSource {
19441892

1945-
@Override
1946-
protected void configure(HttpSecurity http) throws Exception {
1947-
// @formatter:off
1948-
http
1949-
.oauth2ResourceServer()
1950-
.jwt();
1951-
// @formatter:on
1952-
}
1893+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = mock(
1894+
AuthenticationDetailsSource.class);
19531895

19541896
@Bean
1955-
BearerTokenAuthenticationConverter converterOne() {
1956-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
1957-
return converter;
1897+
SecurityFilterChain web(HttpSecurity http) throws Exception {
1898+
// @formatter:off
1899+
http
1900+
.authorizeRequests((authorize) -> authorize
1901+
.anyRequest().authenticated()
1902+
)
1903+
.oauth2ResourceServer((oauth2) -> oauth2
1904+
.jwt(withDefaults())
1905+
.withObjectPostProcessor(new ObjectPostProcessor<BearerTokenAuthenticationFilter>() {
1906+
@Override
1907+
public BearerTokenAuthenticationFilter postProcess(BearerTokenAuthenticationFilter object) {
1908+
object.setAuthenticationDetailsSource(CustomAuthenticationDetailsSource.this.authenticationDetailsSource);
1909+
return object;
1910+
}
1911+
})
1912+
);
1913+
return http.build();
19581914
}
19591915

19601916
@Bean
1961-
BearerTokenAuthenticationConverter converterTwo() {
1962-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
1963-
return converter;
1917+
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource() {
1918+
return this.authenticationDetailsSource;
19641919
}
1965-
19661920
}
19671921

19681922
@EnableWebSecurity

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverter.java

Lines changed: 0 additions & 77 deletions
This file was deleted.

0 commit comments

Comments
 (0)