Add token endpoint implementation
Fixes gh-67
This commit is contained in:
parent
485b7e9319
commit
8dbdd6640c
@ -33,6 +33,7 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @author Krisztian Toth
|
||||
* @author Madhu Bhat
|
||||
* @since 0.0.1
|
||||
* @see RegisteredClient
|
||||
* @see OAuth2AccessToken
|
||||
@ -74,6 +75,15 @@ public class OAuth2Authorization implements Serializable {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the access token {@link OAuth2AccessToken} in the {@link OAuth2Authorization}.
|
||||
*
|
||||
* @param accessToken the access token
|
||||
*/
|
||||
public final void setAccessToken(OAuth2AccessToken accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute(s) associated to the authorization.
|
||||
*
|
||||
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Joe Grandja
|
||||
* @author Madhu Bhat
|
||||
*/
|
||||
public class OAuth2AccessTokenAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
@ -49,4 +50,13 @@ public class OAuth2AccessTokenAuthenticationToken extends AbstractAuthentication
|
||||
public Object getPrincipal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access token {@link OAuth2AccessToken}.
|
||||
*
|
||||
* @return the access token
|
||||
*/
|
||||
public OAuth2AccessToken getAccessToken() {
|
||||
return this.accessToken;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Joe Grandja
|
||||
* @author Madhu Bhat
|
||||
*/
|
||||
public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
@ -57,4 +58,13 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti
|
||||
public Object getPrincipal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code.
|
||||
*
|
||||
* @return the code
|
||||
*/
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,31 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.web;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
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.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.TokenType;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
@ -26,19 +47,145 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* This {@code Filter} is used by the client to obtain an access token by presenting
|
||||
* its authorization grant.
|
||||
*
|
||||
* <p>
|
||||
* It converts the OAuth 2.0 Access Token Request to {@link OAuth2AuthorizationCodeAuthenticationToken},
|
||||
* which is then authenticated by the {@link AuthenticationManager} and gets back
|
||||
* {@link OAuth2AccessTokenAuthenticationToken} which has the {@link OAuth2AccessToken} if the request
|
||||
* was successfully authenticated. The {@link OAuth2AccessToken} is then updated in the in-flight {@link OAuth2Authorization}
|
||||
* and sent back to the client. In case the authentication fails, an HTTP 401 (Unauthorized) response is returned.
|
||||
*
|
||||
* <p>
|
||||
* By default, this {@code Filter} responds to access token requests
|
||||
* at the {@code URI} {@code /oauth2/token} and {@code HttpMethod} {@code POST}
|
||||
* using the default {@link AntPathRequestMatcher}.
|
||||
*
|
||||
* <p>
|
||||
* The default base {@code URI} {@code /oauth2/token} may be overridden
|
||||
* via the constructor {@link #OAuth2TokenEndpointFilter(OAuth2AuthorizationService, AuthenticationManager, String)}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @author Madhu Bhat
|
||||
*/
|
||||
public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
|
||||
private Converter<HttpServletRequest, Authentication> authorizationGrantConverter;
|
||||
/**
|
||||
* The default endpoint {@code URI} for access token requests.
|
||||
*/
|
||||
private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/oauth2/token";
|
||||
|
||||
private Converter<HttpServletRequest, Authentication> authorizationGrantConverter = this::convert;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private OAuth2AuthorizationService authorizationService;
|
||||
private RequestMatcher uriMatcher;
|
||||
private ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2TokenEndpointFilter} using the provided parameters.
|
||||
*
|
||||
* @param authorizationService the authorization service implementation
|
||||
* @param authenticationManager the authentication manager implementation
|
||||
*/
|
||||
public OAuth2TokenEndpointFilter(OAuth2AuthorizationService authorizationService, AuthenticationManager authenticationManager) {
|
||||
Assert.notNull(authorizationService, "authorizationService cannot be null");
|
||||
Assert.notNull(authenticationManager, "authenticationManager cannot be null");
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.uriMatcher = new AntPathRequestMatcher(DEFAULT_TOKEN_ENDPOINT_URI, HttpMethod.POST.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2TokenEndpointFilter} using the provided parameters.
|
||||
*
|
||||
* @param authorizationService the authorization service implementation
|
||||
* @param authenticationManager the authentication manager implementation
|
||||
* @param tokenEndpointUri the token endpoint's uri
|
||||
*/
|
||||
public OAuth2TokenEndpointFilter(OAuth2AuthorizationService authorizationService, AuthenticationManager authenticationManager,
|
||||
String tokenEndpointUri) {
|
||||
Assert.notNull(authorizationService, "authorizationService cannot be null");
|
||||
Assert.notNull(authenticationManager, "authenticationManager cannot be null");
|
||||
Assert.hasText(tokenEndpointUri, "tokenEndpointUri cannot be empty");
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.uriMatcher = new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
if (uriMatcher.matches(request)) {
|
||||
try {
|
||||
if (validateAccessTokenRequest(request)) {
|
||||
OAuth2AuthorizationCodeAuthenticationToken authCodeAuthToken =
|
||||
(OAuth2AuthorizationCodeAuthenticationToken) authorizationGrantConverter.convert(request);
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken =
|
||||
(OAuth2AccessTokenAuthenticationToken) authenticationManager.authenticate(authCodeAuthToken);
|
||||
if (accessTokenAuthenticationToken.isAuthenticated()) {
|
||||
OAuth2Authorization authorization = authorizationService
|
||||
.findByTokenAndTokenType(authCodeAuthToken.getCode(), TokenType.AUTHORIZATION_CODE);
|
||||
authorization.setAccessToken(accessTokenAuthenticationToken.getAccessToken());
|
||||
authorizationService.save(authorization);
|
||||
writeSuccessResponse(response, accessTokenAuthenticationToken.getAccessToken());
|
||||
} else {
|
||||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT));
|
||||
}
|
||||
}
|
||||
} catch (OAuth2AuthenticationException exception) {
|
||||
SecurityContextHolder.clearContext();
|
||||
writeFailureResponse(response, exception.getError());
|
||||
}
|
||||
} else {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateAccessTokenRequest(HttpServletRequest request) {
|
||||
if (StringUtils.isEmpty(request.getParameter(OAuth2ParameterNames.CODE))
|
||||
|| StringUtils.isEmpty(request.getParameter(OAuth2ParameterNames.REDIRECT_URI))
|
||||
|| StringUtils.isEmpty(request.getParameter(OAuth2ParameterNames.GRANT_TYPE))) {
|
||||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST));
|
||||
} else if (!AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(request.getParameter(OAuth2ParameterNames.GRANT_TYPE))) {
|
||||
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private OAuth2AuthorizationCodeAuthenticationToken convert(HttpServletRequest request) {
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
return new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
request.getParameter(OAuth2ParameterNames.CODE),
|
||||
clientPrincipal,
|
||||
request.getParameter(OAuth2ParameterNames.REDIRECT_URI)
|
||||
);
|
||||
}
|
||||
|
||||
private void writeSuccessResponse(HttpServletResponse response, OAuth2AccessToken body) throws IOException {
|
||||
try (Writer out = response.getWriter()) {
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "no-store");
|
||||
response.setHeader(HttpHeaders.PRAGMA, "no-cache");
|
||||
out.write(objectMapper.writeValueAsString(body));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFailureResponse(HttpServletResponse response, OAuth2Error error) throws IOException {
|
||||
try (Writer out = response.getWriter()) {
|
||||
if (error.getErrorCode().equals(OAuth2ErrorCodes.INVALID_CLIENT)) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
} else {
|
||||
response.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||
}
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
out.write(objectMapper.writeValueAsString(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2020 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.authorization.web;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.TokenType;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2TokenEndpointFilter}.
|
||||
*
|
||||
* @author Madhu Bhat
|
||||
*/
|
||||
public class OAuth2TokenEndpointFilterTests {
|
||||
|
||||
private OAuth2TokenEndpointFilter filter;
|
||||
private OAuth2AuthorizationService authorizationService = mock(OAuth2AuthorizationService.class);
|
||||
private AuthenticationManager authenticationManager = mock(AuthenticationManager.class);
|
||||
private FilterChain filterChain = mock(FilterChain.class);
|
||||
private String requestUri;
|
||||
private static final RegisteredClient REGISTERED_CLIENT = TestRegisteredClients.registeredClient().build();
|
||||
private static final String PRINCIPAL_NAME = "principal";
|
||||
private static final String AUTHORIZATION_CODE = "code";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.filter = new OAuth2TokenEndpointFilter(this.authorizationService, this.authenticationManager);
|
||||
this.requestUri = "/oauth2/token";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorServiceAndManagerWhenNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> {
|
||||
new OAuth2TokenEndpointFilter(null, null);
|
||||
}).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorServiceAndManagerAndEndpointWhenNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> {
|
||||
new OAuth2TokenEndpointFilter(null, null, null);
|
||||
}).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenNotTokenRequestThenNextFilter() throws Exception {
|
||||
this.requestUri = "/path";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", this.requestUri);
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verify(this.filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenAccessTokenRequestWithoutGrantTypeThenRespondWithBadRequest() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.CODE, "testAuthCode");
|
||||
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, "testRedirectUri");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
|
||||
assertThat(response.getContentAsString()).isEqualTo("{\"errorCode\":\"invalid_request\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenAccessTokenRequestWithoutCodeThenRespondWithBadRequest() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, "testGrantType");
|
||||
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, "testRedirectUri");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
|
||||
assertThat(response.getContentAsString()).isEqualTo("{\"errorCode\":\"invalid_request\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenAccessTokenRequestWithoutRedirectUriThenRespondWithBadRequest() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, "testGrantType");
|
||||
request.addParameter(OAuth2ParameterNames.CODE, "testAuthCode");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
|
||||
assertThat(response.getContentAsString()).isEqualTo("{\"errorCode\":\"invalid_request\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenAccessTokenRequestWithoutAuthCodeGrantTypeThenRespondWithBadRequest() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, "testGrantType");
|
||||
request.addParameter(OAuth2ParameterNames.CODE, "testAuthCode");
|
||||
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, "testRedirectUri");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
|
||||
assertThat(response.getContentAsString()).isEqualTo("{\"errorCode\":\"unsupported_grant_type\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenAccessTokenRequestIsNotAuthenticatedThenRespondWithUnauthorized() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue());
|
||||
request.addParameter(OAuth2ParameterNames.CODE, "testAuthCode");
|
||||
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, "testRedirectUri");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Authentication clientPrincipal = mock(Authentication.class);
|
||||
RegisteredClient registeredClient = mock(RegisteredClient.class);
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
OAuth2AccessToken.TokenType.BEARER, "testToken", Instant.now().minusSeconds(60), Instant.now());
|
||||
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
|
||||
.principalName(PRINCIPAL_NAME)
|
||||
.attribute(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE)
|
||||
.build();
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken =
|
||||
new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken);
|
||||
accessTokenAuthenticationToken.setAuthenticated(false);
|
||||
|
||||
when(this.authorizationService.findByTokenAndTokenType(anyString(), any(TokenType.class))).thenReturn(authorization);
|
||||
when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(accessTokenAuthenticationToken);
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
verify(this.authorizationService, times(0)).save(authorization);
|
||||
verify(this.authenticationManager, times(1)).authenticate(any(Authentication.class));
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
|
||||
assertThat(response.getContentAsString())
|
||||
.isEqualTo("{\"errorCode\":\"invalid_client\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenValidAccessTokenRequestThenRespondWithAccessToken() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", this.requestUri);
|
||||
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue());
|
||||
request.addParameter(OAuth2ParameterNames.CODE, "testAuthCode");
|
||||
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, "testRedirectUri");
|
||||
request.setServletPath(this.requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Authentication clientPrincipal = mock(Authentication.class);
|
||||
RegisteredClient registeredClient = mock(RegisteredClient.class);
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
OAuth2AccessToken.TokenType.BEARER, "testToken", Instant.now().minusSeconds(60), Instant.now());
|
||||
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
|
||||
.principalName(PRINCIPAL_NAME)
|
||||
.attribute(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE)
|
||||
.build();
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken =
|
||||
new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken);
|
||||
accessTokenAuthenticationToken.setAuthenticated(true);
|
||||
|
||||
when(this.authorizationService.findByTokenAndTokenType(anyString(), any(TokenType.class))).thenReturn(authorization);
|
||||
when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(accessTokenAuthenticationToken);
|
||||
|
||||
this.filter.doFilter(request, response, this.filterChain);
|
||||
|
||||
verifyNoInteractions(this.filterChain);
|
||||
verify(this.authorizationService, times(1)).save(authorization);
|
||||
verify(this.authenticationManager, times(1)).authenticate(any(Authentication.class));
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(response.getContentAsString()).contains("\"tokenValue\":\"testToken\"");
|
||||
assertThat(response.getContentAsString()).contains("\"tokenType\":{\"value\":\"Bearer\"}");
|
||||
assertThat(response.getHeader(HttpHeaders.CACHE_CONTROL)).isEqualTo("no-store");
|
||||
assertThat(response.getHeader(HttpHeaders.PRAGMA)).isEqualTo("no-cache");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user