Explorar el Código

Add Additional Tests To BearerTokenAuthenticationFilterTests

Issue gh-14750

Signed-off-by: Max Batischev <mblancer@mail.ru>
Max Batischev hace 4 meses
padre
commit
30577bd291

+ 177 - 0
oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/authentication/BearerTokenAuthenticationFilterTests.java

@@ -52,6 +52,7 @@ import org.springframework.security.oauth2.server.resource.authentication.Bearer
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
 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.context.RequestAttributeSecurityContextRepository;
 import org.springframework.security.web.context.SecurityContextRepository;
@@ -74,6 +75,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
 @ExtendWith(MockitoExtension.class)
 public class BearerTokenAuthenticationFilterTests {
 
+	private static final String TEST_TOKEN = "token";
+
 	@Mock
 	AuthenticationEntryPoint authenticationEntryPoint;
 
@@ -92,6 +95,9 @@ public class BearerTokenAuthenticationFilterTests {
 	@Mock
 	AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
 
+	@Mock
+	AuthenticationConverter authenticationConverter;
+
 	MockHttpServletRequest request;
 
 	MockHttpServletResponse response;
@@ -321,6 +327,171 @@ public class BearerTokenAuthenticationFilterTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void doFilterWhenBearerTokenPresentAndConverterSetThenAuthenticates() throws ServletException, IOException {
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		ArgumentCaptor<BearerTokenAuthenticationToken> captor = ArgumentCaptor
+			.forClass(BearerTokenAuthenticationToken.class);
+		verify(this.authenticationManager).authenticate(captor.capture());
+		assertThat(captor.getValue().getPrincipal()).isEqualTo(TEST_TOKEN);
+		assertThat(this.request.getAttribute(RequestAttributeSecurityContextRepository.DEFAULT_REQUEST_ATTR_NAME))
+			.isNotNull();
+	}
+
+	@Test
+	public void doFilterWhenSecurityContextRepositoryAndConverterSetThenSaves() throws ServletException, IOException {
+		SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("test", "password");
+		given(this.authenticationManager.authenticate(any())).willReturn(expectedAuthentication);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+		filter.setSecurityContextRepository(securityContextRepository);
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		ArgumentCaptor<BearerTokenAuthenticationToken> captor = ArgumentCaptor
+			.forClass(BearerTokenAuthenticationToken.class);
+		verify(this.authenticationManager).authenticate(captor.capture());
+		assertThat(captor.getValue().getPrincipal()).isEqualTo(TEST_TOKEN);
+		ArgumentCaptor<SecurityContext> contextArg = ArgumentCaptor.forClass(SecurityContext.class);
+		verify(securityContextRepository).saveContext(contextArg.capture(), eq(this.request), eq(this.response));
+		assertThat(contextArg.getValue().getAuthentication().getName()).isEqualTo(expectedAuthentication.getName());
+	}
+
+	@Test
+	public void doFilterWhenUsingAuthenticationManagerResolverAndConverterSetThenAuthenticates() throws Exception {
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManagerResolver));
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		given(this.authenticationManagerResolver.resolve(any())).willReturn(this.authenticationManager);
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		ArgumentCaptor<BearerTokenAuthenticationToken> captor = ArgumentCaptor
+			.forClass(BearerTokenAuthenticationToken.class);
+		verify(this.authenticationManager).authenticate(captor.capture());
+		assertThat(captor.getValue().getPrincipal()).isEqualTo(TEST_TOKEN);
+		assertThat(this.request.getAttribute(RequestAttributeSecurityContextRepository.DEFAULT_REQUEST_ATTR_NAME))
+			.isNotNull();
+	}
+
+	@Test
+	public void doFilterWhenNoBearerTokenPresentAndConverterSetThenDoesNotAuthenticate()
+			throws ServletException, IOException {
+		given(this.authenticationConverter.convert(this.request)).willReturn(null);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verifyNoMoreInteractions(this.authenticationManager);
+	}
+
+	@Test
+	public void doFilterWhenMalformedBearerTokenAndConverterSetThenPropagatesError()
+			throws ServletException, IOException {
+		BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST,
+				"description", "uri");
+		OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error);
+		given(this.authenticationConverter.convert(this.request)).willThrow(exception);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verifyNoMoreInteractions(this.authenticationManager);
+		verify(this.authenticationEntryPoint).commence(this.request, this.response, exception);
+	}
+
+	@Test
+	public void doFilterWhenAuthenticationFailsWithDefaultHandlerAndConverterSetThenPropagatesError()
+			throws ServletException, IOException {
+		BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED,
+				"description", "uri");
+		OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error);
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		given(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))).willThrow(exception);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verify(this.authenticationEntryPoint).commence(this.request, this.response, exception);
+	}
+
+	@Test
+	public void doFilterWhenAuthenticationFailsWithCustomHandlerAndConverterSetThenPropagatesError()
+			throws ServletException, IOException {
+		BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED,
+				"description", "uri");
+		OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error);
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		given(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))).willThrow(exception);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+		filter.setAuthenticationFailureHandler(this.authenticationFailureHandler);
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verify(this.authenticationFailureHandler).onAuthenticationFailure(this.request, this.response, exception);
+	}
+
+	@Test
+	public void doFilterWhenConverterSetAndAuthenticationServiceExceptionThenRethrows() {
+		AuthenticationServiceException exception = new AuthenticationServiceException("message");
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		given(this.authenticationManager.authenticate(any())).willThrow(exception);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+
+		assertThatExceptionOfType(AuthenticationServiceException.class)
+			.isThrownBy(() -> filter.doFilter(this.request, this.response, this.filterChain));
+	}
+
+	@Test
+	public void doFilterWhenConverterSetAndCustomEntryPointAndAuthenticationErrorThenUses()
+			throws ServletException, IOException {
+		AuthenticationException exception = new InvalidBearerTokenException("message");
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		given(this.authenticationManager.authenticate(any())).willThrow(exception);
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+		AuthenticationEntryPoint entrypoint = mock(AuthenticationEntryPoint.class);
+		filter.setAuthenticationEntryPoint(entrypoint);
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verify(entrypoint).commence(any(), any(), any(InvalidBearerTokenException.class));
+	}
+
+	@Test
+	public void doFilterWhenConverterSetCustomSecurityContextHolderStrategyThenUses()
+			throws ServletException, IOException {
+		given(this.authenticationConverter.convert(this.request))
+			.willReturn(new BearerTokenAuthenticationToken(TEST_TOKEN));
+		BearerTokenAuthenticationFilter filter = addMocksWithConverter(
+				new BearerTokenAuthenticationFilter(this.authenticationManager));
+		SecurityContextHolderStrategy strategy = mock(SecurityContextHolderStrategy.class);
+		given(strategy.createEmptyContext()).willReturn(new SecurityContextImpl());
+		filter.setSecurityContextHolderStrategy(strategy);
+
+		filter.doFilter(this.request, this.response, this.filterChain);
+
+		verify(strategy).setContext(any());
+	}
+
 	private BearerTokenAuthenticationFilter addMocks(BearerTokenAuthenticationFilter filter) {
 		filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
 		filter.setBearerTokenResolver(this.bearerTokenResolver);
@@ -335,4 +506,10 @@ public class BearerTokenAuthenticationFilterTests {
 		verifyNoMoreInteractions(this.authenticationManager);
 	}
 
+	private BearerTokenAuthenticationFilter addMocksWithConverter(BearerTokenAuthenticationFilter filter) {
+		filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
+		filter.setAuthenticationConverter(this.authenticationConverter);
+		return filter;
+	}
+
 }