From 8ac819ad14bf3f510f5fa9b0636e9eda0a136a78 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Wed, 20 Apr 2022 11:14:10 +0800 Subject: [PATCH] chore: cleanup deprecated class (#1859) --- .../app/identity/authentication/Context.java | 2 +- .../DefaultOAuth2TokenContext.java | 2 +- ...tUsernamePasswordAuthenticationFilter.java | 153 ----------- ...h2RefreshTokenAuthenticationConverter.java | 6 +- .../OAuth2TokenEndpointFilter.java | 15 +- .../authentication/OAuth2TokenGenerator.java | 2 +- .../authentication/OAuth2TokenType.java | 2 +- .../authentication/ProviderContext.java | 2 +- .../authentication/SecurityConstant.java | 28 -- ...namePasswordAuthenticationFilterTests.java | 253 ------------------ 10 files changed, 11 insertions(+), 454 deletions(-) delete mode 100644 src/main/java/run/halo/app/identity/authentication/JwtUsernamePasswordAuthenticationFilter.java delete mode 100644 src/main/java/run/halo/app/identity/authentication/SecurityConstant.java delete mode 100644 src/test/java/run/halo/app/authentication/JwtUsernamePasswordAuthenticationFilterTests.java diff --git a/src/main/java/run/halo/app/identity/authentication/Context.java b/src/main/java/run/halo/app/identity/authentication/Context.java index 17e367e35..afa76d40d 100644 --- a/src/main/java/run/halo/app/identity/authentication/Context.java +++ b/src/main/java/run/halo/app/identity/authentication/Context.java @@ -7,7 +7,7 @@ import org.springframework.util.Assert; * A facility for holding information associated to a specific context. * * @author guqing - * @date 2022-04-14 + * @since 2.0.0 */ public interface Context { /** diff --git a/src/main/java/run/halo/app/identity/authentication/DefaultOAuth2TokenContext.java b/src/main/java/run/halo/app/identity/authentication/DefaultOAuth2TokenContext.java index e4e7ee5bb..941d92beb 100644 --- a/src/main/java/run/halo/app/identity/authentication/DefaultOAuth2TokenContext.java +++ b/src/main/java/run/halo/app/identity/authentication/DefaultOAuth2TokenContext.java @@ -8,7 +8,7 @@ import org.springframework.util.Assert; * Default implementation of {@link OAuth2TokenContext}. * * @author guqing - * @date 2022-04-14 + * @since 2.0.0 */ public record DefaultOAuth2TokenContext(Map context) implements OAuth2TokenContext { public DefaultOAuth2TokenContext { diff --git a/src/main/java/run/halo/app/identity/authentication/JwtUsernamePasswordAuthenticationFilter.java b/src/main/java/run/halo/app/identity/authentication/JwtUsernamePasswordAuthenticationFilter.java deleted file mode 100644 index 860776395..000000000 --- a/src/main/java/run/halo/app/identity/authentication/JwtUsernamePasswordAuthenticationFilter.java +++ /dev/null @@ -1,153 +0,0 @@ -package run.halo.app.identity.authentication; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.time.temporal.ChronoUnit; -import java.util.Map; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.server.ServletServerHttpResponse; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.core.AuthorizationGrantType; -import org.springframework.security.oauth2.core.OAuth2AccessToken; -import org.springframework.security.oauth2.core.OAuth2Error; -import org.springframework.security.oauth2.core.OAuth2RefreshToken; -import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; -import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; -import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; -import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter; -import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * Processes an authentication client request. Called - * {@code AuthenticationProcessingFilter} prior to Spring Security 3.0. - *

- * Request parameter must present two parameters to this filter: a username and password. The - * default parameter names to use are contained in the static fields - * {@link #SPRING_SECURITY_FORM_USERNAME_KEY} and - * {@link #SPRING_SECURITY_FORM_PASSWORD_KEY}. The parameter names can also be changed by - * setting the {@code usernameParameter} and {@code passwordParameter} properties. - *

- * This filter by default responds to the URL {@code /api/v1/oauth2/login}. - * - * @author guqing - * @see UsernamePasswordAuthenticationFilter - * @see AbstractAuthenticationProcessingFilter - * @see OAuth2AccessTokenAuthenticationToken - * @since 2.0.0 - */ -public class JwtUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { - /** - * The default endpoint {@code URI} for access token requests. - */ - private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/api/v1/oauth2/token"; - private final HttpMessageConverter accessTokenHttpResponseConverter = - new OAuth2AccessTokenResponseHttpMessageConverter(); - private final HttpMessageConverter errorHttpResponseConverter = - new OAuth2ErrorHttpMessageConverter(); - - private boolean postOnly = true; - - public JwtUsernamePasswordAuthenticationFilter() { - this(DEFAULT_TOKEN_ENDPOINT_URI, null); - } - - public JwtUsernamePasswordAuthenticationFilter(String defaultFilterProcessesUrl) { - this(defaultFilterProcessesUrl, null); - } - - public JwtUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) { - this(DEFAULT_TOKEN_ENDPOINT_URI, authenticationManager); - } - - public JwtUsernamePasswordAuthenticationFilter(String defaultFilterProcessesUrl, - AuthenticationManager authenticationManager) { - super(authenticationManager); - if (!StringUtils.hasText(defaultFilterProcessesUrl)) { - throw new IllegalArgumentException("tokenEndpointUri cannot be empty."); - } - setFilterProcessesUrl(defaultFilterProcessesUrl); - setAuthenticationSuccessHandler(this::sendAccessTokenResponse); - setAuthenticationFailureHandler(this::sendErrorResponse); - } - - @Override - public Authentication attemptAuthentication(HttpServletRequest request, - HttpServletResponse response) - throws AuthenticationException { - - if (this.postOnly && !HttpMethod.POST.name().equals(request.getMethod())) { - throw new AuthenticationServiceException( - "Authentication method not supported: " + request.getMethod()); - } - String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); - if (!AuthorizationGrantType.PASSWORD.getValue().equals(grantType)) { - return null; - } - String username = obtainUsername(request); - username = (username != null) ? username : ""; - username = username.trim(); - String password = obtainPassword(request); - password = (password != null) ? password : ""; - UsernamePasswordAuthenticationToken authRequest = - new UsernamePasswordAuthenticationToken(username, password); - // Allow subclasses to set the "details" property - setDetails(request, authRequest); - return this.getAuthenticationManager().authenticate(authRequest); - } - - private void sendAccessTokenResponse(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException { - - OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = - (OAuth2AccessTokenAuthenticationToken) authentication; - - OAuth2AccessToken accessToken = accessTokenAuthentication.getAccessToken(); - OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken(); - Map additionalParameters = - accessTokenAuthentication.getAdditionalParameters(); - - OAuth2AccessTokenResponse.Builder builder = - OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) - .tokenType(accessToken.getTokenType()) - .scopes(accessToken.getScopes()); - if (accessToken.getIssuedAt() != null && accessToken.getExpiresAt() != null) { - builder.expiresIn( - ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt())); - } - if (refreshToken != null) { - builder.refreshToken(refreshToken.getTokenValue()); - } - if (!CollectionUtils.isEmpty(additionalParameters)) { - builder.additionalParameters(additionalParameters); - } - OAuth2AccessTokenResponse accessTokenResponse = builder.build(); - ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); - this.accessTokenHttpResponseConverter.write(accessTokenResponse, null, httpResponse); - } - - private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response, - AuthenticationException exception) throws IOException { - - //OAuth2Error error = ((AuthenticationServiceException) exception).getMessage(); - ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); - httpResponse.setStatusCode(HttpStatus.BAD_REQUEST); - this.errorHttpResponseConverter.write(new OAuth2Error(exception.getMessage()), null, - httpResponse); - } - - @Override - public void setPostOnly(boolean postOnly) { - this.postOnly = postOnly; - super.setPostOnly(postOnly); - } -} diff --git a/src/main/java/run/halo/app/identity/authentication/OAuth2RefreshTokenAuthenticationConverter.java b/src/main/java/run/halo/app/identity/authentication/OAuth2RefreshTokenAuthenticationConverter.java index 35966f7d9..e1ad54a03 100644 --- a/src/main/java/run/halo/app/identity/authentication/OAuth2RefreshTokenAuthenticationConverter.java +++ b/src/main/java/run/halo/app/identity/authentication/OAuth2RefreshTokenAuthenticationConverter.java @@ -28,8 +28,6 @@ import org.springframework.util.StringUtils; * @since 2.0.0 */ public class OAuth2RefreshTokenAuthenticationConverter implements AuthenticationConverter { - static final String ACCESS_TOKEN_REQUEST_ERROR_URI = - "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; @Nullable @Override @@ -48,7 +46,7 @@ public class OAuth2RefreshTokenAuthenticationConverter implements Authentication || parameters.get(OAuth2ParameterNames.REFRESH_TOKEN).size() != 1) { OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REFRESH_TOKEN, - ACCESS_TOKEN_REQUEST_ERROR_URI); + OAuth2EndpointUtils.ERROR_URI); } // scope (OPTIONAL) @@ -58,7 +56,7 @@ public class OAuth2RefreshTokenAuthenticationConverter implements Authentication OAuth2EndpointUtils.throwError( OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE, - ACCESS_TOKEN_REQUEST_ERROR_URI); + OAuth2EndpointUtils.ERROR_URI); } Set requestedScopes = null; if (StringUtils.hasText(scope)) { diff --git a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenEndpointFilter.java b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenEndpointFilter.java index 79d864142..4da174ff4 100644 --- a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenEndpointFilter.java +++ b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenEndpointFilter.java @@ -47,8 +47,6 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter { */ private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/api/v1/oauth2/token"; - private static final String DEFAULT_ERROR_URI = - "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; private final AuthenticationManager authenticationManager; private final RequestMatcher tokenEndpointMatcher; private final HttpMessageConverter accessTokenHttpResponseConverter = @@ -103,14 +101,15 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter { try { String[] grantTypes = request.getParameterValues(OAuth2ParameterNames.GRANT_TYPE); if (grantTypes == null || grantTypes.length != 1) { - throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.GRANT_TYPE); + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, + OAuth2ParameterNames.GRANT_TYPE, OAuth2EndpointUtils.ERROR_URI); } Authentication authorizationGrantAuthentication = this.authenticationConverter.convert(request); if (authorizationGrantAuthentication == null) { - throwError(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE, - OAuth2ParameterNames.GRANT_TYPE); + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE, + OAuth2ParameterNames.GRANT_TYPE, OAuth2EndpointUtils.ERROR_URI); } if (authorizationGrantAuthentication instanceof AbstractAuthenticationToken) { ((AbstractAuthenticationToken) authorizationGrantAuthentication) @@ -221,10 +220,4 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter { httpResponse.setStatusCode(HttpStatus.BAD_REQUEST); this.errorHttpResponseConverter.write(error, null, httpResponse); } - - private static void throwError(String errorCode, String parameterName) { - OAuth2Error error = - new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, DEFAULT_ERROR_URI); - throw new OAuth2AuthenticationException(error); - } } diff --git a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenGenerator.java b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenGenerator.java index f27fdc5e6..bfecbb1ec 100644 --- a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenGenerator.java +++ b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenGenerator.java @@ -10,7 +10,7 @@ import org.springframework.security.oauth2.core.OAuth2Token; * * @param the type of the OAuth 2.0 Token * @author guqing - * @date 2022-04-14 + * @since 2.0.0 * @see OAuth2Token * @see OAuth2TokenContext * @see ClaimAccessor diff --git a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenType.java b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenType.java index 282d371da..dc982d410 100644 --- a/src/main/java/run/halo/app/identity/authentication/OAuth2TokenType.java +++ b/src/main/java/run/halo/app/identity/authentication/OAuth2TokenType.java @@ -5,7 +5,7 @@ import org.springframework.util.Assert; /** * @author guqing - * @date 2022-04-14 + * @since 2.0.0 */ public record OAuth2TokenType(String value) implements Serializable { public static final OAuth2TokenType ACCESS_TOKEN = new OAuth2TokenType("access_token"); diff --git a/src/main/java/run/halo/app/identity/authentication/ProviderContext.java b/src/main/java/run/halo/app/identity/authentication/ProviderContext.java index bc9bfa2c5..4d14762a1 100644 --- a/src/main/java/run/halo/app/identity/authentication/ProviderContext.java +++ b/src/main/java/run/halo/app/identity/authentication/ProviderContext.java @@ -8,7 +8,7 @@ import org.springframework.util.Assert; * A context that holds information of the Provider. * * @author guqing - * @date 2022-04-14 + * @since 2.0.0 */ public record ProviderContext(ProviderSettings providerSettings, @Nullable Supplier issuerSupplier) { diff --git a/src/main/java/run/halo/app/identity/authentication/SecurityConstant.java b/src/main/java/run/halo/app/identity/authentication/SecurityConstant.java deleted file mode 100644 index 9eb97582d..000000000 --- a/src/main/java/run/halo/app/identity/authentication/SecurityConstant.java +++ /dev/null @@ -1,28 +0,0 @@ -package run.halo.app.identity.authentication; - -/** - * @author guqing - * @date 2022-04-13 - */ -public interface SecurityConstant { - - /** - * 30 mins - */ - long EXPIRATION_TIME = 1_800_000; - - /** - * Token prefix - */ - String TOKEN_PREFIX = "Bearer"; - - /** - * Authentication header - */ - String HEADER_STRING = "Authorization"; - - /** - * login uri - */ - String LOGIN_URL = "/api/v1/oauth/login"; -} diff --git a/src/test/java/run/halo/app/authentication/JwtUsernamePasswordAuthenticationFilterTests.java b/src/test/java/run/halo/app/authentication/JwtUsernamePasswordAuthenticationFilterTests.java deleted file mode 100644 index 97908cd2f..000000000 --- a/src/test/java/run/halo/app/authentication/JwtUsernamePasswordAuthenticationFilterTests.java +++ /dev/null @@ -1,253 +0,0 @@ -package run.halo.app.authentication; - -import static java.util.Map.entry; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.InstanceOfAssertFactories.type; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.time.Duration; -import java.time.Instant; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.springframework.http.HttpStatus; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.mock.http.client.MockClientHttpResponse; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -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.AuthorizationGrantType; -import org.springframework.security.oauth2.core.OAuth2AccessToken; -import org.springframework.security.oauth2.core.OAuth2RefreshToken; -import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; -import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; -import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.security.web.authentication.WebAuthenticationDetails; -import run.halo.app.identity.authentication.JwtUsernamePasswordAuthenticationFilter; -import run.halo.app.identity.authentication.OAuth2AccessTokenAuthenticationToken; - -/** - * Tests for {@link JwtUsernamePasswordAuthenticationFilter}. - * - * @author guqing - * @since 2.0.0 - */ -@Disabled -public class JwtUsernamePasswordAuthenticationFilterTests { - private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/api/v1/oauth2/login"; - private static final String REMOTE_ADDRESS = "remote-address"; - private AuthenticationManager authenticationManager; - private JwtUsernamePasswordAuthenticationFilter filter; - - private final HttpMessageConverter accessTokenHttpResponseConverter = - new OAuth2AccessTokenResponseHttpMessageConverter(); - - @BeforeEach - public void setUp() { - this.authenticationManager = mock(AuthenticationManager.class); - this.filter = new JwtUsernamePasswordAuthenticationFilter(this.authenticationManager); - } - - @AfterEach - public void cleanup() { - SecurityContextHolder.clearContext(); - } - - @Test - public void constructorWhenTokenEndpointUriNullThenThrowIllegalArgumentException() { - assertThatThrownBy( - () -> new JwtUsernamePasswordAuthenticationFilter(null, this.authenticationManager)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("tokenEndpointUri cannot be empty."); - } - - @Test - public void setAuthenticationDetailsSourceWhenNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.filter.setAuthenticationDetailsSource(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("AuthenticationDetailsSource required"); - } - - @Test - public void setAuthenticationSuccessHandlerWhenNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.filter.setAuthenticationSuccessHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("successHandler cannot be null"); - } - - @Test - public void setAuthenticationFailureHandlerWhenNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.filter.setAuthenticationFailureHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("failureHandler cannot be null"); - } - - @Test - public void doFilterWhenNotTokenRequestThenNotProcessed() throws Exception { - String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); - request.setServletPath(requestUri); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain filterChain = mock(FilterChain.class); - - this.filter.doFilter(request, response, filterChain); - - verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - } - - @Test - public void doFilterWhenTokenRequestGetThenNotProcessed() throws Exception { - String requestUri = DEFAULT_TOKEN_ENDPOINT_URI; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain filterChain = mock(FilterChain.class); - - AuthenticationFailureHandler authenticationFailureHandler = - mock(AuthenticationFailureHandler.class); - filter.setAuthenticationFailureHandler(authenticationFailureHandler); - - this.filter.doFilter(request, response, filterChain); - - verify(authenticationFailureHandler).onAuthenticationFailure(any(HttpServletRequest.class), - any(HttpServletResponse.class), any(AuthenticationException.class)); - - verifyNoInteractions(filterChain); - } - - @Test - public void doFilterWhenAuthorizationCodeTokenRequestThenAccessTokenResponse() - throws Exception { - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "token", - Instant.now(), Instant.now().plus(Duration.ofHours(1)), - new HashSet<>(Arrays.asList("scope1", "scope2"))); - OAuth2RefreshToken refreshToken = new OAuth2RefreshToken( - "refresh-token", Instant.now(), Instant.now().plus(Duration.ofDays(1))); - Authentication clientPrincipal = - new UsernamePasswordAuthenticationToken("guqing", "123456"); - Map - additionalParameters = Collections.singletonMap("custom-param", "custom-value"); - OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = - new OAuth2AccessTokenAuthenticationToken(clientPrincipal, accessToken, refreshToken, - additionalParameters); - - when(this.authenticationManager.authenticate(any())).thenReturn(accessTokenAuthentication); - - SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); - securityContext.setAuthentication(clientPrincipal); - SecurityContextHolder.setContext(securityContext); - - MockHttpServletRequest request = createClientTokenRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain filterChain = mock(FilterChain.class); - - this.filter.doFilter(request, response, filterChain); - - verifyNoInteractions(filterChain); - - ArgumentCaptor - authorizationCodeAuthenticationCaptor = - ArgumentCaptor.forClass(UsernamePasswordAuthenticationToken.class); - verify(this.authenticationManager).authenticate( - authorizationCodeAuthenticationCaptor.capture()); - - UsernamePasswordAuthenticationToken accessTokenAuthenticationToken = - authorizationCodeAuthenticationCaptor.getValue(); - assertThat(accessTokenAuthenticationToken.getName()).isEqualTo("guqing"); - assertThat(accessTokenAuthenticationToken.getDetails()) - .asInstanceOf(type(WebAuthenticationDetails.class)) - .extracting(WebAuthenticationDetails::getRemoteAddress) - .isEqualTo(REMOTE_ADDRESS); - - assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); - OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response); - - OAuth2AccessToken accessTokenResult = accessTokenResponse.getAccessToken(); - assertThat(accessTokenResult.getTokenType()).isEqualTo(accessToken.getTokenType()); - assertThat(accessTokenResult.getTokenValue()).isEqualTo(accessToken.getTokenValue()); - assertThat(accessTokenResult.getIssuedAt()).isBetween( - accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); - assertThat(accessTokenResult.getExpiresAt()).isBetween( - accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); - assertThat(accessTokenResult.getScopes()).isEqualTo(accessToken.getScopes()); - assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo( - refreshToken.getTokenValue()); - assertThat(accessTokenResponse.getAdditionalParameters()).containsExactly( - entry("custom-param", "custom-value")); - } - - @Test - public void doFilterWhenCustomAuthenticationSuccessHandlerThenUsed() throws Exception { - AuthenticationSuccessHandler authenticationSuccessHandler = - mock(AuthenticationSuccessHandler.class); - this.filter.setAuthenticationSuccessHandler(authenticationSuccessHandler); - - Authentication clientPrincipal = - new UsernamePasswordAuthenticationToken("guqing", "123456"); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "token", - Instant.now(), Instant.now().plus(Duration.ofHours(1)), - new HashSet<>(Arrays.asList("scope1", "scope2"))); - OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = - new OAuth2AccessTokenAuthenticationToken(clientPrincipal, accessToken); - - when(this.authenticationManager.authenticate(any())).thenReturn(accessTokenAuthentication); - - SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); - securityContext.setAuthentication(clientPrincipal); - SecurityContextHolder.setContext(securityContext); - - MockHttpServletRequest request = createClientTokenRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain filterChain = mock(FilterChain.class); - - this.filter.doFilter(request, response, filterChain); - - verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), any()); - } - - private OAuth2AccessTokenResponse readAccessTokenResponse(MockHttpServletResponse response) - throws Exception { - MockClientHttpResponse httpResponse = new MockClientHttpResponse( - response.getContentAsByteArray(), HttpStatus.valueOf(response.getStatus())); - return this.accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, - httpResponse); - } - - private static MockHttpServletRequest createClientTokenRequest() { - String requestUri = DEFAULT_TOKEN_ENDPOINT_URI; - MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); - request.setServletPath(requestUri); - request.setRemoteAddr(REMOTE_ADDRESS); - request.addParameter("username", "guqing"); - request.addParameter("password", "123456"); - - request.addParameter(OAuth2ParameterNames.GRANT_TYPE, - AuthorizationGrantType.PASSWORD.getValue()); - request.addParameter("custom-param-1", "custom-value-1"); - - return request; - } -}