|
@@ -15,12 +15,19 @@
|
|
*/
|
|
*/
|
|
package org.springframework.security.oauth2.server.authorization.web.authentication;
|
|
package org.springframework.security.oauth2.server.authorization.web.authentication;
|
|
|
|
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.function.Consumer;
|
|
|
|
+
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
+
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.converter.HttpMessageConverter;
|
|
import org.springframework.http.converter.HttpMessageConverter;
|
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
|
+import org.springframework.security.authentication.TestingAuthenticationToken;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
|
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
|
@@ -29,29 +36,16 @@ import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
|
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
|
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
|
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
|
|
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
|
|
-import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService;
|
|
|
|
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
|
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
|
-import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
|
|
|
-import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
|
|
|
|
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
|
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationContext;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationContext;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
|
-import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
|
|
|
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
|
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
|
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
|
|
|
|
|
-import java.time.Instant;
|
|
|
|
-import java.time.temporal.ChronoUnit;
|
|
|
|
-import java.util.Collections;
|
|
|
|
-import java.util.HashMap;
|
|
|
|
-import java.util.Map;
|
|
|
|
-import java.util.Set;
|
|
|
|
-import java.util.function.Consumer;
|
|
|
|
-
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
-import static org.assertj.core.api.Assertions.within;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
* Tests for {@link OAuth2AccessTokenResponseAuthenticationSuccessHandler}.
|
|
* Tests for {@link OAuth2AccessTokenResponseAuthenticationSuccessHandler}.
|
|
@@ -60,14 +54,12 @@ import static org.assertj.core.api.Assertions.within;
|
|
*/
|
|
*/
|
|
public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
|
|
public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
|
|
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
|
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
|
-
|
|
|
|
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
|
|
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
|
|
new OAuth2AccessTokenResponseHttpMessageConverter();
|
|
new OAuth2AccessTokenResponseHttpMessageConverter();
|
|
-
|
|
|
|
private final OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
|
private final OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
|
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
|
|
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
|
|
-
|
|
|
|
- private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler = new OAuth2AccessTokenResponseAuthenticationSuccessHandler();
|
|
|
|
|
|
+ private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler =
|
|
|
|
+ new OAuth2AccessTokenResponseAuthenticationSuccessHandler();
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void setAccessTokenResponseCustomizerWhenNullThenThrowIllegalArgumentException() {
|
|
public void setAccessTokenResponseCustomizerWhenNullThenThrowIllegalArgumentException() {
|
|
@@ -79,39 +71,40 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
- public void onAuthenticationSuccessWhenProvidedRequestResponseAndAuthThenWritesAccessTokenToHttpResponse() throws Exception {
|
|
|
|
|
|
+ public void onAuthenticationSuccessWhenAuthenticationProvidedThenAccessTokenResponse() throws Exception {
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
|
|
|
- Instant issuedAt = Instant.now();
|
|
|
|
- Instant expiresAt = issuedAt.plusSeconds(300);
|
|
|
|
- OAuth2Authorization testAuthorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
|
|
|
|
|
|
+ OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
|
|
|
|
+ OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
|
|
|
|
+ OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
|
|
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
|
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
|
- Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient, clientPrincipal,
|
|
|
|
- testAuthorization.getAccessToken().getToken(), testAuthorization.getRefreshToken().getToken(),
|
|
|
|
- additionalParameters);
|
|
|
|
|
|
+ Authentication authentication = new OAuth2AccessTokenAuthenticationToken(
|
|
|
|
+ this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters);
|
|
|
|
|
|
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication);
|
|
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication);
|
|
|
|
|
|
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
|
|
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
|
|
- assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token");
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isCloseTo(issuedAt, within(2, ChronoUnit.SECONDS));
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isCloseTo(expiresAt, within(2, ChronoUnit.SECONDS));
|
|
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue());
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType());
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween(
|
|
|
|
+ accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(
|
|
|
|
+ accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
|
|
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
|
|
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
|
|
- assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token");
|
|
|
|
|
|
+ assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue());
|
|
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
|
|
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
|
|
Map.of("param1", "value1")
|
|
Map.of("param1", "value1")
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
- public void onAuthenticationSuccessWhenAuthenticationIsNotInstanceOfOAuth2AccessTokenAuthenticationTokenThenThrowOAuth2AuthenticationException() {
|
|
|
|
|
|
+ public void onAuthenticationSuccessWhenInvalidAuthenticationTypeThenThrowOAuth2AuthenticationException() {
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
|
|
|
assertThatThrownBy(() ->
|
|
assertThatThrownBy(() ->
|
|
- this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, Set.of(), Map.of())))
|
|
|
|
|
|
+ this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, new TestingAuthenticationToken(this.clientPrincipal, null)))
|
|
.isInstanceOf(OAuth2AuthenticationException.class)
|
|
.isInstanceOf(OAuth2AuthenticationException.class)
|
|
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
|
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
|
.extracting("errorCode")
|
|
.extracting("errorCode")
|
|
@@ -119,48 +112,38 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests {
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
- public void onAuthenticationSuccessWhenAccessTokenResponseIsCustomizedViaAccessTokenResponseCustomizerThenResponseHasCustomizedFields() throws Exception {
|
|
|
|
|
|
+ public void onAuthenticationSuccessWhenAccessTokenResponseCustomizerSetThenAccessTokenResponseCustomized() throws Exception {
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
- OAuth2AuthorizationService authorizationService = new InMemoryOAuth2AuthorizationService();
|
|
|
|
- OAuth2Authorization testAuthorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
|
|
|
|
- authorizationService.save(testAuthorization);
|
|
|
|
-
|
|
|
|
- Instant issuedAt = Instant.now();
|
|
|
|
- Instant expiresAt = issuedAt.plusSeconds(300);
|
|
|
|
- OAuth2AccessToken accessToken = testAuthorization.getAccessToken().getToken();
|
|
|
|
- OAuth2RefreshToken refreshToken = testAuthorization.getRefreshToken().getToken();
|
|
|
|
|
|
+
|
|
|
|
+ OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient).build();
|
|
|
|
+ OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
|
|
|
|
+ OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
|
|
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
|
Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
|
- Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters);
|
|
|
|
-
|
|
|
|
- Consumer<OAuth2AccessTokenAuthenticationContext> accessTokenResponseCustomizer = (OAuth2AccessTokenAuthenticationContext authenticationContext) -> {
|
|
|
|
- OAuth2AccessTokenAuthenticationToken authenticationToken = authenticationContext.getAuthentication();
|
|
|
|
- OAuth2AccessTokenResponse.Builder accessTokenResponse = authenticationContext.getAccessTokenResponse();
|
|
|
|
- OAuth2Authorization authorization = authorizationService.findByToken(
|
|
|
|
- authenticationToken.getAccessToken().getTokenValue(),
|
|
|
|
- OAuth2TokenType.ACCESS_TOKEN
|
|
|
|
- );
|
|
|
|
- Map<String, Object> customParams = Map.of(
|
|
|
|
- "authorization_id", authorization.getId(),
|
|
|
|
- "registered_client_id", authorization.getRegisteredClientId()
|
|
|
|
- );
|
|
|
|
- Map<String, Object> allParams = new HashMap<>(authenticationToken.getAdditionalParameters());
|
|
|
|
- allParams.putAll(customParams);
|
|
|
|
- accessTokenResponse.additionalParameters(allParams);
|
|
|
|
|
|
+ Authentication authentication = new OAuth2AccessTokenAuthenticationToken(
|
|
|
|
+ this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters);
|
|
|
|
+
|
|
|
|
+ Consumer<OAuth2AccessTokenAuthenticationContext> accessTokenResponseCustomizer = (authenticationContext) -> {
|
|
|
|
+ OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = authenticationContext.getAuthentication();
|
|
|
|
+ Map<String, Object> additionalParams = new HashMap<>(accessTokenAuthentication.getAdditionalParameters());
|
|
|
|
+ additionalParams.put("authorization_id", authorization.getId());
|
|
|
|
+ authenticationContext.getAccessTokenResponse().additionalParameters(additionalParams);
|
|
};
|
|
};
|
|
-
|
|
|
|
this.authenticationSuccessHandler.setAccessTokenResponseCustomizer(accessTokenResponseCustomizer);
|
|
this.authenticationSuccessHandler.setAccessTokenResponseCustomizer(accessTokenResponseCustomizer);
|
|
|
|
+
|
|
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication);
|
|
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication);
|
|
|
|
|
|
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
|
|
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
|
|
- assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token");
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isCloseTo(issuedAt, within(2, ChronoUnit.SECONDS));
|
|
|
|
- assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isCloseTo(expiresAt, within(2, ChronoUnit.SECONDS));
|
|
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue());
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType());
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween(
|
|
|
|
+ accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
|
|
|
|
+ assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(
|
|
|
|
+ accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
|
|
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
|
|
assertThat(accessTokenResponse.getRefreshToken()).isNotNull();
|
|
- assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token");
|
|
|
|
|
|
+ assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue());
|
|
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
|
|
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf(
|
|
- Map.of("param1", "value1", "authorization_id", "id", "registered_client_id", "registration-1")
|
|
|
|
|
|
+ Map.of("param1", "value1", "authorization_id", "id")
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|