From 31f310fd22b0c2f6b1a0e01ec16821364245bb8b Mon Sep 17 00:00:00 2001 From: Jeongjin Kim Date: Wed, 19 Aug 2020 16:40:04 +0900 Subject: [PATCH] Add BearerTokenAuthenticationConverter BearerTokenAuthenticationConverter is introduced to solve the problem of not being able to change AuthenticationDetailsSource. BearerTokenAuthenticationFilter delegates to BearerTokenAuthenticationConverter the task of creating BearerTokenAuthenticationToken and setting AuthenticationDetailsSource. BearerTokenAuthenticationConverter is customizable and the customized converter can be used in BearerTokenAuthenticationFilter. Closes gh-8840 --- .../OAuth2ResourceServerConfigurer.java | 34 ++++++- .../OAuth2ResourceServerConfigurerTests.java | 95 +++++++++++++++++++ .../BearerTokenAuthenticationConverter.java | 81 ++++++++++++++++ .../web/BearerTokenAuthenticationFilter.java | 42 +++++--- ...arerTokenAuthenticationConverterTests.java | 87 +++++++++++++++++ .../BearerTokenAuthenticationFilterTests.java | 10 ++ 6 files changed, 333 insertions(+), 16 deletions(-) create mode 100644 oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverter.java create mode 100644 oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverterTests.java diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index c27a779ea3..271175ad2e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; +import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider; import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider; @@ -51,6 +52,7 @@ import org.springframework.security.oauth2.server.resource.web.DefaultBearerToke import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.util.matcher.AndRequestMatcher; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; import org.springframework.security.web.util.matcher.NegatedRequestMatcher; @@ -78,6 +80,8 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * authentication failures are handled *
  • {@link #bearerTokenResolver(BearerTokenResolver)} - customizes how to resolve a * bearer token from the request
  • + *
  • {@link #bearerTokenAuthenticationConverter(AuthenticationConverter)}
  • - + * customizes how to convert a bear token authentication from the request *
  • {@link #jwt(Customizer)} - enables Jwt-encoded bearer token support
  • *
  • {@link #opaqueToken(Customizer)} - enables opaque bearer token support
  • * @@ -159,6 +163,8 @@ public final class OAuth2ResourceServerConfigurer bearerTokenAuthenticationConverter( + AuthenticationConverter authenticationConverter) { + Assert.notNull(authenticationConverter, "authenticationConverter cannot be null"); + this.authenticationConverter = authenticationConverter; + return this; + } + public JwtConfigurer jwt() { if (this.jwtConfigurer == null) { this.jwtConfigurer = new JwtConfigurer(this.context); @@ -252,8 +265,11 @@ public final class OAuth2ResourceServerConfigurer authenticationManager; } + + this.authenticationConverter = getBearerTokenAuthenticationConverter(); + BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver); - filter.setBearerTokenResolver(bearerTokenResolver); + filter.setAuthenticationConverter(this.authenticationConverter); filter.setAuthenticationEntryPoint(this.authenticationEntryPoint); filter = postProcess(filter); http.addFilter(filter); @@ -347,6 +363,20 @@ public final class OAuth2ResourceServerConfigurer 0) { + this.authenticationConverter = this.context.getBean(BearerTokenAuthenticationConverter.class); + } + else { + BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter(); + converter.setBearerTokenResolver(getBearerTokenResolver()); + this.authenticationConverter = converter; + } + } + return this.authenticationConverter; + } + public class JwtConfigurer { private final ApplicationContext context; diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java index e7c7de2cd8..5072e6d768 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java @@ -33,6 +33,7 @@ import java.util.Map; import java.util.stream.Collectors; import javax.annotation.PreDestroy; +import javax.servlet.http.HttpServletRequest; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; @@ -108,7 +109,9 @@ import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtTimestampValidator; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.oauth2.jwt.TestJwts; +import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication; +import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver; @@ -720,6 +723,72 @@ public class OAuth2ResourceServerConfigurerTests { assertThat(oauth2.getBearerTokenResolver()).isInstanceOf(DefaultBearerTokenResolver.class); } + @Test + public void getBearerTokenAuthenticationConverterWhenDuplicateConverterBeansAndAnotherOnTheDslThenTheDslOneIsUsed() { + BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter(); + BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter(); + GenericWebApplicationContext context = new GenericWebApplicationContext(); + context.registerBean("converterOne", BearerTokenAuthenticationConverter.class, () -> converterBean); + context.registerBean("converterTwo", BearerTokenAuthenticationConverter.class, () -> converterBean); + this.spring.context(context).autowire(); + OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); + oauth2.bearerTokenAuthenticationConverter(converter); + assertThat(oauth2.getBearerTokenAuthenticationConverter()).isEqualTo(converter); + } + + @Test + public void getBearerTokenAuthenticationConverterWhenDuplicateConverterBeansThenWiringException() { + assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> this.spring + .register(MultipleBearerTokenAuthenticationConverterBeansConfig.class, JwtDecoderConfig.class) + .autowire()).withRootCauseInstanceOf(NoUniqueBeanDefinitionException.class); + } + + @Test + public void getBearerTokenAuthenticationConverterWhenConverterBeanAndAnotherOnTheDslThenTheDslOneIsUsed() { + BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter(); + BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter(); + GenericWebApplicationContext context = new GenericWebApplicationContext(); + context.registerBean(BearerTokenAuthenticationConverter.class, () -> converterBean); + this.spring.context(context).autowire(); + OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); + oauth2.bearerTokenAuthenticationConverter(converter); + assertThat(oauth2.getBearerTokenAuthenticationConverter()).isEqualTo(converter); + } + + @Test + public void getBearerTokenAuthenticationConverterWhenNoConverterSpecifiedThenTheDefaultIsUsed() { + ApplicationContext context = this.spring.context(new GenericWebApplicationContext()).getContext(); + OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); + assertThat(oauth2.getBearerTokenAuthenticationConverter()) + .isInstanceOf(BearerTokenAuthenticationConverter.class); + } + + @Test + public void getBearerTokenAuthenticationConverterWhenConverterBeanRegisteredThenBeanIsUsed() { + BearerTokenAuthenticationConverter converterBean = new BearerTokenAuthenticationConverter(); + GenericWebApplicationContext context = new GenericWebApplicationContext(); + context.registerBean(BearerTokenAuthenticationConverter.class, () -> converterBean); + this.spring.context(context).autowire(); + OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); + assertThat(oauth2.getBearerTokenAuthenticationConverter()).isEqualTo(converterBean); + + } + + @Test + public void getBearerTokenAuthenticationConverterWhenOnlyResolverBeanRegisteredThenUseTheResolver() { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + BearerTokenResolver resolverBean = (request) -> "bearer customToken"; + GenericWebApplicationContext context = new GenericWebApplicationContext(); + context.registerBean(BearerTokenResolver.class, () -> resolverBean); + this.spring.context(context).autowire(); + OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); + BearerTokenAuthenticationToken bearerTokenAuthenticationToken = (BearerTokenAuthenticationToken) oauth2 + .getBearerTokenAuthenticationConverter().convert(servletRequest); + String token = bearerTokenAuthenticationToken.getToken(); + assertThat(token).isEqualTo("bearer customToken"); + + } + @Test public void requestWhenCustomJwtDecoderWiredOnDslThenUsed() throws Exception { this.spring.register(CustomJwtDecoderOnDsl.class, BasicController.class).autowire(); @@ -1871,6 +1940,32 @@ public class OAuth2ResourceServerConfigurerTests { } + @EnableWebSecurity + static class MultipleBearerTokenAuthenticationConverterBeansConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .oauth2ResourceServer() + .jwt(); + // @formatter:on + } + + @Bean + BearerTokenAuthenticationConverter converterOne() { + BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter(); + return converter; + } + + @Bean + BearerTokenAuthenticationConverter converterTwo() { + BearerTokenAuthenticationConverter converter = new BearerTokenAuthenticationConverter(); + return converter; + } + + } + @EnableWebSecurity static class CustomJwtDecoderOnDsl extends WebSecurityConfigurerAdapter { diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverter.java new file mode 100644 index 0000000000..a10ffd1c3d --- /dev/null +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverter.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.oauth2.server.resource.authentication; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.security.authentication.AuthenticationDetailsSource; +import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; +import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; +import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver; +import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.Assert; + +/** + * Converts from a HttpServletRequest to {@link BearerTokenAuthenticationToken} that can + * be authenticated. Null authentication possible if there was no Authorization header + * with Bearer Token. + * + * @author Jeongjin Kim + * @since 5.5 + */ +public final class BearerTokenAuthenticationConverter implements AuthenticationConverter { + + private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); + + private BearerTokenResolver bearerTokenResolver; + + public BearerTokenAuthenticationConverter() { + this.bearerTokenResolver = new DefaultBearerTokenResolver(); + } + + @Override + public BearerTokenAuthenticationToken convert(HttpServletRequest request) { + String token = this.bearerTokenResolver.resolve(request); + + if (token == null) { + return null; + } + + BearerTokenAuthenticationToken authenticationRequest = new BearerTokenAuthenticationToken(token); + authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); + return authenticationRequest; + } + + /** + * Set the {@link BearerTokenResolver} to use. Defaults to + * {@link DefaultBearerTokenResolver}. + * @param bearerTokenResolver the {@code BearerTokenResolver} to use + */ + public void setBearerTokenResolver(BearerTokenResolver bearerTokenResolver) { + Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null"); + this.bearerTokenResolver = bearerTokenResolver; + } + + /** + * Set the {@link AuthenticationDetailsSource} to use. Defaults to + * {@link WebAuthenticationDetailsSource}. + * @param authenticationDetailsSource the {@code AuthenticationDetailsSource} to use + */ + public void setAuthenticationDetailsSource( + AuthenticationDetailsSource authenticationDetailsSource) { + Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null"); + this.authenticationDetailsSource = authenticationDetailsSource; + } + +} diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java index 551101d0ef..a945cc479a 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java @@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.log.LogMessage; -import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManagerResolver; import org.springframework.security.authentication.AuthenticationServiceException; @@ -32,12 +31,12 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; +import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.util.Assert; import org.springframework.web.filter.OncePerRequestFilter; @@ -61,10 +60,6 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter private final AuthenticationManagerResolver authenticationManagerResolver; - private final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); - - private BearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver(); - private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint(); private AuthenticationFailureHandler authenticationFailureHandler = (request, response, exception) -> { @@ -74,6 +69,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter this.authenticationEntryPoint.commence(request, response, exception); }; + private AuthenticationConverter authenticationConverter = new BearerTokenAuthenticationConverter(); + /** * Construct a {@code BearerTokenAuthenticationFilter} using the provided parameter(s) * @param authenticationManagerResolver @@ -106,22 +103,21 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String token; + Authentication authenticationRequest; try { - token = this.bearerTokenResolver.resolve(request); + authenticationRequest = this.authenticationConverter.convert(request); } - catch (OAuth2AuthenticationException invalid) { + catch (AuthenticationException invalid) { this.logger.trace("Sending to authentication entry point since failed to resolve bearer token", invalid); this.authenticationEntryPoint.commence(request, response, invalid); return; } - if (token == null) { + if (authenticationRequest == null) { this.logger.trace("Did not process request since did not find bearer token"); filterChain.doFilter(request, response); return; } - BearerTokenAuthenticationToken authenticationRequest = new BearerTokenAuthenticationToken(token); - authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); + try { AuthenticationManager authenticationManager = this.authenticationManagerResolver.resolve(request); Authentication authenticationResult = authenticationManager.authenticate(authenticationRequest); @@ -144,10 +140,17 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter * Set the {@link BearerTokenResolver} to use. Defaults to * {@link DefaultBearerTokenResolver}. * @param bearerTokenResolver the {@code BearerTokenResolver} to use + * @deprecated Instead, use {@link BearerTokenAuthenticationConverter} explicitly + * @see BearerTokenAuthenticationConverter */ + @Deprecated public void setBearerTokenResolver(BearerTokenResolver bearerTokenResolver) { Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null"); - this.bearerTokenResolver = bearerTokenResolver; + Assert.isTrue(this.authenticationConverter instanceof BearerTokenAuthenticationConverter, + "bearerTokenResolver and authenticationConverter cannot both be customized in this filter. " + + "Since you've customized the authenticationConverter, " + + "please consider configuring the bearerTokenResolver there."); + ((BearerTokenAuthenticationConverter) this.authenticationConverter).setBearerTokenResolver(bearerTokenResolver); } /** @@ -171,4 +174,15 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter this.authenticationFailureHandler = authenticationFailureHandler; } + /** + * Set the {@link AuthenticationConverter} to use. Defaults to + * {@link BearerTokenAuthenticationConverter}. + * @param authenticationConverter the {@code AuthenticationConverter} to use + * @since 5.5 + */ + public void setAuthenticationConverter(AuthenticationConverter authenticationConverter) { + Assert.notNull(authenticationConverter, "authenticationConverter cannot be null"); + this.authenticationConverter = authenticationConverter; + } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverterTests.java new file mode 100644 index 0000000000..8f46a381dd --- /dev/null +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationConverterTests.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.oauth2.server.resource.authentication; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link BearerTokenAuthenticationConverter} + * + * @author Jeongjin Kim + * @since 5.5 + */ +@RunWith(MockitoJUnitRunner.class) +public class BearerTokenAuthenticationConverterTests { + + private BearerTokenAuthenticationConverter converter; + + @Before + public void setup() { + this.converter = new BearerTokenAuthenticationConverter(); + } + + @Test + public void setBearerTokenResolverWithNullThenThrowsException() { + // @formatter:off + assertThatIllegalArgumentException() + .isThrownBy(() -> this.converter.setBearerTokenResolver(null)) + .withMessageContaining("bearerTokenResolver cannot be null"); + // @formatter:on + } + + @Test + public void setAuthenticationDetailsSourceWithNullThenThrowsException() { + // @formatter:off + assertThatIllegalArgumentException() + .isThrownBy(() -> this.converter.setAuthenticationDetailsSource(null)) + .withMessageContaining("authenticationDetailsSource cannot be null"); + // @formatter:on + } + + @Test + public void convertWhenNoBearerTokenHeaderThenNull() { + HttpServletRequest request = mock(HttpServletRequest.class); + + BearerTokenAuthenticationToken convert = this.converter.convert(request); + + assertThat(convert).isNull(); + } + + @Test + public void convertWhenBearerTokenThenBearerTokenAuthenticationToken() { + HttpServletRequest request = mock(HttpServletRequest.class); + given(request.getHeader(HttpHeaders.AUTHORIZATION)).willReturn("Bearer token"); + + BearerTokenAuthenticationToken token = this.converter.convert(request); + + assertThat(token.getToken()).isEqualTo("token"); + } + +} diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java index 3882f73f72..af4b350370 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java @@ -187,6 +187,16 @@ public class BearerTokenAuthenticationFilterTests { // @formatter:on } + @Test + public void setAuthenticationConverterWhenNullThenThrowsException() { + // @formatter:off + BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager); + assertThatIllegalArgumentException() + .isThrownBy(() -> filter.setAuthenticationConverter(null)) + .withMessageContaining("authenticationConverter cannot be null"); + // @formatter:on + } + @Test public void constructorWhenNullAuthenticationManagerThenThrowsException() { // @formatter:off