Skip to content

Commit eaab42a

Browse files
committed
Polish BearerTokenAuthenticationConverter Support
- Moved to BearerTokenAuthenticationFilter constructor to align with AuthenticationFilter - Undeprecated BearerTokenResolver to reduce number of migration scenarios - Updated to 7.0 schema - Added migration docs Issue gh-14750
1 parent 30577bd commit eaab42a

File tree

14 files changed

+203
-376
lines changed

14 files changed

+203
-376
lines changed

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

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import java.util.function.Supplier;
2424

2525
import jakarta.servlet.http.HttpServletRequest;
26-
import org.apache.commons.logging.Log;
27-
import org.apache.commons.logging.LogFactory;
2826

2927
import org.springframework.context.ApplicationContext;
3028
import org.springframework.core.convert.converter.Converter;
@@ -44,7 +42,6 @@
4442
import org.springframework.security.oauth2.jwt.Jwt;
4543
import org.springframework.security.oauth2.jwt.JwtDecoder;
4644
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
47-
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken;
4845
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
4946
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider;
5047
import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider;
@@ -69,7 +66,6 @@
6966
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
7067
import org.springframework.security.web.util.matcher.RequestMatcher;
7168
import org.springframework.util.Assert;
72-
import org.springframework.util.StringUtils;
7369
import org.springframework.web.accept.ContentNegotiationStrategy;
7470
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
7571

@@ -200,21 +196,17 @@ public OAuth2ResourceServerConfigurer<H> authenticationManagerResolver(
200196
return this;
201197
}
202198

203-
/**
204-
* @deprecated please use {@link #authenticationConverter} instead
205-
*/
206-
@Deprecated
207199
public OAuth2ResourceServerConfigurer<H> bearerTokenResolver(BearerTokenResolver bearerTokenResolver) {
208200
Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null");
209-
this.authenticationConverter = new BearerTokenResolverAuthenticationConverterAdapter(bearerTokenResolver);
201+
this.authenticationConverter = new BearerTokenResolverHoldingAuthenticationConverter(bearerTokenResolver);
210202
return this;
211203
}
212204

213205
/**
214206
* Sets the {@link AuthenticationConverter} to use.
215207
* @param authenticationConverter the authentication converter
216208
* @return the {@link OAuth2ResourceServerConfigurer} for further configuration
217-
* @since 6.5
209+
* @since 7.0
218210
*/
219211
public OAuth2ResourceServerConfigurer<H> authenticationConverter(AuthenticationConverter authenticationConverter) {
220212
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
@@ -299,10 +291,9 @@ public void configure(H http) {
299291
resolver = (request) -> authenticationManager;
300292
}
301293

302-
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver);
303294
AuthenticationConverter converter = getAuthenticationConverter();
304295
this.requestMatcher.setAuthenticationConverter(converter);
305-
filter.setAuthenticationConverter(converter);
296+
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver, converter);
306297
filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
307298
filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
308299
filter = postProcess(filter);
@@ -394,7 +385,7 @@ AuthenticationConverter getAuthenticationConverter() {
394385
}
395386
else if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) {
396387
BearerTokenResolver bearerTokenResolver = this.context.getBean(BearerTokenResolver.class);
397-
this.authenticationConverter = new BearerTokenResolverAuthenticationConverterAdapter(bearerTokenResolver);
388+
this.authenticationConverter = new BearerTokenResolverHoldingAuthenticationConverter(bearerTokenResolver);
398389
}
399390
else {
400391
this.authenticationConverter = new BearerTokenAuthenticationConverter();
@@ -404,7 +395,7 @@ else if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0)
404395

405396
BearerTokenResolver getBearerTokenResolver() {
406397
AuthenticationConverter authenticationConverter = getAuthenticationConverter();
407-
if (authenticationConverter instanceof BearerTokenResolverAuthenticationConverterAdapter bearer) {
398+
if (authenticationConverter instanceof OAuth2ResourceServerConfigurer.BearerTokenResolverHoldingAuthenticationConverter bearer) {
408399
return bearer.bearerTokenResolver;
409400
}
410401
return null;
@@ -614,24 +605,22 @@ void setAuthenticationConverter(AuthenticationConverter authenticationConverter)
614605

615606
}
616607

617-
private static final class BearerTokenResolverAuthenticationConverterAdapter implements AuthenticationConverter {
618-
619-
private final Log logger = LogFactory.getLog(BearerTokenResolverAuthenticationConverterAdapter.class);
608+
private static final class BearerTokenResolverHoldingAuthenticationConverter implements AuthenticationConverter {
620609

621610
private final BearerTokenResolver bearerTokenResolver;
622611

623-
BearerTokenResolverAuthenticationConverterAdapter(BearerTokenResolver bearerTokenResolver) {
612+
private final AuthenticationConverter authenticationConverter;
613+
614+
BearerTokenResolverHoldingAuthenticationConverter(BearerTokenResolver bearerTokenResolver) {
624615
this.bearerTokenResolver = bearerTokenResolver;
616+
BearerTokenAuthenticationConverter authenticationConverter = new BearerTokenAuthenticationConverter();
617+
authenticationConverter.setBearerTokenResolver(bearerTokenResolver);
618+
this.authenticationConverter = authenticationConverter;
625619
}
626620

627621
@Override
628622
public Authentication convert(HttpServletRequest request) {
629-
String token = this.bearerTokenResolver.resolve(request);
630-
if (!StringUtils.hasText(token)) {
631-
this.logger.trace("Did not process request since did not find bearer token");
632-
return null;
633-
}
634-
return new BearerTokenAuthenticationToken(token);
623+
return this.authenticationConverter.convert(request);
635624
}
636625

637626
}

config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
7272

7373
static final String BEARER_TOKEN_RESOLVER = "bearerTokenResolver";
7474

75-
static final String AUTHENTICATION_CONVERTER = "authenticationConverter";
76-
7775
static final String AUTHENTICATION_ENTRY_POINT = "authenticationEntryPoint";
7876

7977
private final BeanReference authenticationManager;
@@ -152,7 +150,7 @@ public BeanDefinition parse(Element oauth2ResourceServer, ParserContext pc) {
152150
this.authenticationFilterSecurityContextHolderStrategy);
153151

154152
if (authenticationConverter != null) {
155-
filterBuilder.addPropertyValue(AUTHENTICATION_CONVERTER, authenticationConverter);
153+
filterBuilder.addConstructorArgValue(authenticationConverter);
156154
}
157155
if (bearerTokenResolver != null) {
158156
filterBuilder.addPropertyValue(BEARER_TOKEN_RESOLVER, bearerTokenResolver);
@@ -170,7 +168,9 @@ private BeanDefinition buildRequestMatcher(BeanMetadataElement bearerTokenResolv
170168
}
171169
BeanDefinitionBuilder requestMatcherBuilder = BeanDefinitionBuilder
172170
.rootBeanDefinition(BearerTokenAuthenticationRequestMatcher.class);
173-
requestMatcherBuilder.addConstructorArgValue(authenticationConverter);
171+
if (authenticationConverter != null) {
172+
requestMatcherBuilder.addConstructorArgValue(authenticationConverter);
173+
}
174174
return requestMatcherBuilder.getBeanDefinition();
175175
}
176176

@@ -409,6 +409,10 @@ static final class BearerTokenAuthenticationRequestMatcher implements RequestMat
409409

410410
private final AuthenticationConverter authenticationConverter;
411411

412+
BearerTokenAuthenticationRequestMatcher() {
413+
this.authenticationConverter = new BearerTokenAuthenticationConverter();
414+
}
415+
412416
BearerTokenAuthenticationRequestMatcher(AuthenticationConverter authenticationConverter) {
413417
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
414418
this.authenticationConverter = authenticationConverter;

config/src/main/resources/org/springframework/security/config/spring-security-6.5.rnc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,6 @@ oauth2-resource-server.attlist &=
650650
oauth2-resource-server.attlist &=
651651
## Reference to a AuthenticationEntryPoint
652652
attribute entry-point-ref {xsd:token}?
653-
oauth2-resource-server.attlist &=
654-
## Reference to a AuthenticationConverter
655-
attribute authentication-converter-ref {xsd:token}?
656653

657654
jwt =
658655
## Configures JWT authentication

config/src/main/resources/org/springframework/security/config/spring-security-6.5.xsd

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,12 +1999,6 @@
19991999
</xs:documentation>
20002000
</xs:annotation>
20012001
</xs:attribute>
2002-
<xs:attribute name="authentication-converter-ref" type="xs:token">
2003-
<xs:annotation>
2004-
<xs:documentation>Reference to a AuthenticationConverter
2005-
</xs:documentation>
2006-
</xs:annotation>
2007-
</xs:attribute>
20082002
</xs:attributeGroup>
20092003
<xs:element name="jwt">
20102004
<xs:annotation>

config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ oauth2-resource-server.attlist &=
650650
oauth2-resource-server.attlist &=
651651
## Reference to a AuthenticationEntryPoint
652652
attribute entry-point-ref {xsd:token}?
653+
oauth2-resource-server.attlist &=
654+
## Reference to a AuthenticationConverter
655+
attribute authentication-converter-ref {xsd:token}?
653656

654657
jwt =
655658
## Configures JWT authentication

config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,12 @@
19991999
</xs:documentation>
20002000
</xs:annotation>
20012001
</xs:attribute>
2002+
<xs:attribute name="authentication-converter-ref" type="xs:token">
2003+
<xs:annotation>
2004+
<xs:documentation>Reference to a AuthenticationConverter
2005+
</xs:documentation>
2006+
</xs:annotation>
2007+
</xs:attribute>
20022008
</xs:attributeGroup>
20032009
<xs:element name="jwt">
20042010
<xs:annotation>

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,16 +2571,20 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
25712571

25722572
@Bean
25732573
AuthenticationConverter authenticationConverterOne() {
2574-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
2575-
converter.setAllowUriQueryParameter(true);
2576-
return converter;
2574+
DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
2575+
resolver.setAllowUriQueryParameter(true);
2576+
BearerTokenAuthenticationConverter authenticationConverter = new BearerTokenAuthenticationConverter();
2577+
authenticationConverter.setBearerTokenResolver(resolver);
2578+
return authenticationConverter;
25772579
}
25782580

25792581
@Bean
25802582
AuthenticationConverter authenticationConverterTwo() {
2581-
BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter();
2582-
converter.setAllowUriQueryParameter(true);
2583-
return converter;
2583+
DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
2584+
resolver.setAllowUriQueryParameter(true);
2585+
BearerTokenAuthenticationConverter authenticationConverter = new BearerTokenAuthenticationConverter();
2586+
authenticationConverter.setBearerTokenResolver(resolver);
2587+
return authenticationConverter;
25842588
}
25852589

25862590
}

docs/modules/ROOT/pages/migration/servlet/oauth2.adoc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,58 @@ fun authenticationConverter(val registrations: RelyingPartyRegistrationRepositor
115115
======
116116

117117
If you must continue using `Saml2AuthenticationTokenConverter`, `OpenSaml4AuthenticationTokenConverter`, or `OpenSaml5AuthenticationTokenConverter` to process GET requests, you can call `setShouldConvertGetRequests` to `true.`
118+
119+
== Provide an AuthenticationConverter to BearerTokenAuthenticationFilter
120+
121+
In Spring Security 7, `BearerTokenAuthenticationFilter#setBearerTokenResolver` and `#setAuthenticaionDetailsSource` are deprecated in favor of configuring those on `BearerTokenAuthenticationConverter`.
122+
123+
The `oauth2ResourceServer` DSL addresses most use cases and you need to nothing.
124+
125+
If you are setting a `BearerTokenResolver` or `AuthenticationDetailsSource` directly on `BearerTokenAuthenticationFilter` similar to the following:
126+
127+
[tabs]
128+
======
129+
Java::
130+
+
131+
[source,java,role="primary"]
132+
----
133+
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(authenticationManager);
134+
filter.setBearerTokenResolver(myBearerTokenResolver);
135+
filter.setAuthenticationDetailsSource(myAuthenticationDetailsSource);
136+
----
137+
138+
Kotlin::
139+
+
140+
[source,kotlin,role="secondary"]
141+
----
142+
val filter = BearerTokenAuthenticationFilter(authenticationManager)
143+
filter.setBearerTokenResolver(myBearerTokenResolver)
144+
filter.setAuthenticationDetailsSource(myAuthenticationDetailsSource)
145+
----
146+
======
147+
148+
you are encouraged to use `BearerTokenAuthenticationConverter` to specify both:
149+
150+
[tabs]
151+
======
152+
Java::
153+
+
154+
[source,java,role="primary"]
155+
----
156+
BearerTokenAuthenticationConverter authenticationConverter =
157+
new BearerTokenAuthenticationConverter();
158+
authenticationConverter.setBearerTokenResolver(myBearerTokenResolver);
159+
authenticationConverter.setAuthenticationDetailsSource(myAuthenticationDetailsSource);
160+
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(authenticationManager, authenicationConverter);
161+
----
162+
163+
Kotlin::
164+
+
165+
[source,kotlin,role="secondary"]
166+
----
167+
val authenticationConverter = BearerTokenAuthenticationConverter()
168+
authenticationConverter.setBearerTokenResolver(myBearerTokenResolver)
169+
authenticationConverter.setAuthenticationDetailsSource(myAuthenticationDetailsSource)
170+
val filter = BearerTokenAuthenticationFilter(authenticationManager, authenticationConverter)
171+
----
172+
======

docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,15 +1266,17 @@ Reference to an `AuthenticationManagerResolver` which will resolve the `Authenti
12661266

12671267
[[nsa-oauth2-resource-server-bearer-token-resolver-ref]]
12681268
* **bearer-token-resolver-ref**
1269-
Reference to a `BearerTokenResolver` which will retrieve the bearer token from the request
1269+
Reference to a `BearerTokenResolver` which will retrieve the bearer token from the request.
1270+
This cannot be used in conjunction with `authentication-converter-ref`
12701271

12711272
[[nsa-oauth2-resource-server-entry-point-ref]]
12721273
* **entry-point-ref**
12731274
Reference to a `AuthenticationEntryPoint` which will handle unauthorized requests
12741275

12751276
[[nsa-oauth2-resource-server-authentication-converter-ref]]
12761277
* **authentication-converter-ref**
1277-
Reference to a `AuthenticationConverter` which convert request to authentication
1278+
Reference to a `AuthenticationConverter` which convert request to authentication.
1279+
This cannot be used in conjunction with `bearer-token-resolver-ref`
12781280

12791281
[[nsa-jwt]]
12801282
== <jwt>

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenResolver.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2025 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,10 +29,7 @@
2929
* @since 5.1
3030
* @see <a href="https://tools.ietf.org/html/rfc6750#section-2" target="_blank">RFC 6750
3131
* Section 2: Authenticated Requests</a>
32-
* @deprecated Use
33-
* {@link org.springframework.security.web.authentication.AuthenticationConverter} instead
3432
*/
35-
@Deprecated
3633
@FunctionalInterface
3734
public interface BearerTokenResolver {
3835

0 commit comments

Comments
 (0)