Add support for opaque access tokens
Closes gh-500
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2022 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.
|
||||
@@ -15,10 +15,16 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
@@ -28,10 +34,12 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
@@ -48,18 +56,26 @@ import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenClaimsSet;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospection;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
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.OAuth2TokenIntrospectionHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.jose.TestJwks;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
|
||||
import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
|
||||
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService;
|
||||
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenClaimsContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
|
||||
@@ -67,6 +83,7 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
@@ -74,7 +91,8 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@@ -88,8 +106,11 @@ public class OAuth2TokenIntrospectionTests {
|
||||
private static EmbeddedDatabase db;
|
||||
private static JWKSource<SecurityContext> jwkSource;
|
||||
private static ProviderSettings providerSettings;
|
||||
private final HttpMessageConverter<OAuth2TokenIntrospection> tokenIntrospectionHttpResponseConverter =
|
||||
private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private static final HttpMessageConverter<OAuth2TokenIntrospection> tokenIntrospectionHttpResponseConverter =
|
||||
new OAuth2TokenIntrospectionHttpMessageConverter();
|
||||
private static final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
|
||||
new OAuth2AccessTokenResponseHttpMessageConverter();
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
@@ -111,6 +132,7 @@ public class OAuth2TokenIntrospectionTests {
|
||||
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
|
||||
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||
providerSettings = ProviderSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
|
||||
accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
db = new EmbeddedDatabaseBuilder()
|
||||
.generateUniqueName(true)
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
@@ -145,9 +167,19 @@ public class OAuth2TokenIntrospectionTests {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
OAuth2AccessToken.TokenType.BEARER, "access-token", issuedAt, expiresAt,
|
||||
new HashSet<>(Arrays.asList("scope1", "scope2")));
|
||||
JwtClaimsSet tokenClaims = TestJwtClaimsSets.jwtClaimsSet().build();
|
||||
// @formatter:off
|
||||
OAuth2TokenClaimsSet accessTokenClaims = OAuth2TokenClaimsSet.builder()
|
||||
.issuer("https://provider.com")
|
||||
.subject("subject")
|
||||
.audience(Collections.singletonList(authorizedRegisteredClient.getClientId()))
|
||||
.issuedAt(issuedAt)
|
||||
.notBefore(issuedAt)
|
||||
.expiresAt(expiresAt)
|
||||
.id("id")
|
||||
.build();
|
||||
// @formatter:on
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations
|
||||
.authorization(authorizedRegisteredClient, accessToken, tokenClaims.getClaims())
|
||||
.authorization(authorizedRegisteredClient, accessToken, accessTokenClaims.getClaims())
|
||||
.build();
|
||||
this.registeredClientRepository.save(authorizedRegisteredClient);
|
||||
this.authorizationService.save(authorization);
|
||||
@@ -155,7 +187,7 @@ public class OAuth2TokenIntrospectionTests {
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(post(providerSettings.getTokenIntrospectionEndpoint())
|
||||
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
|
||||
.with(httpBasic(introspectRegisteredClient.getClientId(), introspectRegisteredClient.getClientSecret())))
|
||||
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
@@ -165,17 +197,17 @@ public class OAuth2TokenIntrospectionTests {
|
||||
assertThat(tokenIntrospectionResponse.getClientId()).isEqualTo(authorizedRegisteredClient.getClientId());
|
||||
assertThat(tokenIntrospectionResponse.getUsername()).isNull();
|
||||
assertThat(tokenIntrospectionResponse.getIssuedAt()).isBetween(
|
||||
accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1));
|
||||
accessTokenClaims.getIssuedAt().minusSeconds(1), accessTokenClaims.getIssuedAt().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getExpiresAt()).isBetween(
|
||||
accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1));
|
||||
accessTokenClaims.getExpiresAt().minusSeconds(1), accessTokenClaims.getExpiresAt().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getScopes()).containsExactlyInAnyOrderElementsOf(accessToken.getScopes());
|
||||
assertThat(tokenIntrospectionResponse.getTokenType()).isEqualTo(accessToken.getTokenType().getValue());
|
||||
assertThat(tokenIntrospectionResponse.getNotBefore()).isBetween(
|
||||
tokenClaims.getNotBefore().minusSeconds(1), tokenClaims.getNotBefore().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getSubject()).isEqualTo(tokenClaims.getSubject());
|
||||
assertThat(tokenIntrospectionResponse.getAudience()).containsExactlyInAnyOrderElementsOf(tokenClaims.getAudience());
|
||||
assertThat(tokenIntrospectionResponse.getIssuer()).isEqualTo(tokenClaims.getIssuer());
|
||||
assertThat(tokenIntrospectionResponse.getId()).isEqualTo(tokenClaims.getId());
|
||||
accessTokenClaims.getNotBefore().minusSeconds(1), accessTokenClaims.getNotBefore().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getSubject()).isEqualTo(accessTokenClaims.getSubject());
|
||||
assertThat(tokenIntrospectionResponse.getAudience()).containsExactlyInAnyOrderElementsOf(accessTokenClaims.getAudience());
|
||||
assertThat(tokenIntrospectionResponse.getIssuer()).isEqualTo(accessTokenClaims.getIssuer());
|
||||
assertThat(tokenIntrospectionResponse.getId()).isEqualTo(accessTokenClaims.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -195,7 +227,7 @@ public class OAuth2TokenIntrospectionTests {
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(post(providerSettings.getTokenIntrospectionEndpoint())
|
||||
.params(getTokenIntrospectionRequestParameters(refreshToken, OAuth2TokenType.REFRESH_TOKEN))
|
||||
.with(httpBasic(introspectRegisteredClient.getClientId(), introspectRegisteredClient.getClientSecret())))
|
||||
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
@@ -217,6 +249,71 @@ public class OAuth2TokenIntrospectionTests {
|
||||
assertThat(tokenIntrospectionResponse.getId()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenObtainReferenceAccessTokenAndIntrospectThenActive() throws Exception {
|
||||
this.spring.register(AuthorizationServerConfiguration.class).autowire();
|
||||
|
||||
// @formatter:off
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build();
|
||||
RegisteredClient authorizedRegisteredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(tokenSettings)
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.registeredClientRepository.save(authorizedRegisteredClient);
|
||||
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(authorizedRegisteredClient).build();
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(post(providerSettings.getTokenEndpoint())
|
||||
.params(getAuthorizationCodeTokenRequestParameters(authorizedRegisteredClient, authorization))
|
||||
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(authorizedRegisteredClient)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
|
||||
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(mvcResult);
|
||||
OAuth2AccessToken accessToken = accessTokenResponse.getAccessToken();
|
||||
|
||||
RegisteredClient introspectRegisteredClient = TestRegisteredClients.registeredClient2().build();
|
||||
this.registeredClientRepository.save(introspectRegisteredClient);
|
||||
|
||||
// @formatter:off
|
||||
mvcResult = this.mvc.perform(post(providerSettings.getTokenIntrospectionEndpoint())
|
||||
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
|
||||
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
|
||||
OAuth2TokenIntrospection tokenIntrospectionResponse = readTokenIntrospectionResponse(mvcResult);
|
||||
|
||||
ArgumentCaptor<OAuth2TokenClaimsContext> accessTokenClaimsContextCaptor = ArgumentCaptor.forClass(OAuth2TokenClaimsContext.class);
|
||||
verify(accessTokenCustomizer).customize(accessTokenClaimsContextCaptor.capture());
|
||||
|
||||
OAuth2TokenClaimsContext accessTokenClaimsContext = accessTokenClaimsContextCaptor.getValue();
|
||||
OAuth2TokenClaimsSet accessTokenClaims = accessTokenClaimsContext.getClaims().build();
|
||||
|
||||
assertThat(tokenIntrospectionResponse.isActive()).isTrue();
|
||||
assertThat(tokenIntrospectionResponse.getClientId()).isEqualTo(authorizedRegisteredClient.getClientId());
|
||||
assertThat(tokenIntrospectionResponse.getUsername()).isNull();
|
||||
assertThat(tokenIntrospectionResponse.getIssuedAt()).isBetween(
|
||||
accessTokenClaims.getIssuedAt().minusSeconds(1), accessTokenClaims.getIssuedAt().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getExpiresAt()).isBetween(
|
||||
accessTokenClaims.getExpiresAt().minusSeconds(1), accessTokenClaims.getExpiresAt().plusSeconds(1));
|
||||
List<String> scopes = new ArrayList<>(accessTokenClaims.getClaim(OAuth2ParameterNames.SCOPE));
|
||||
assertThat(tokenIntrospectionResponse.getScopes()).containsExactlyInAnyOrderElementsOf(scopes);
|
||||
assertThat(tokenIntrospectionResponse.getTokenType()).isEqualTo(accessToken.getTokenType().getValue());
|
||||
assertThat(tokenIntrospectionResponse.getNotBefore()).isBetween(
|
||||
accessTokenClaims.getNotBefore().minusSeconds(1), accessTokenClaims.getNotBefore().plusSeconds(1));
|
||||
assertThat(tokenIntrospectionResponse.getSubject()).isEqualTo(accessTokenClaims.getSubject());
|
||||
assertThat(tokenIntrospectionResponse.getAudience()).containsExactlyInAnyOrderElementsOf(accessTokenClaims.getAudience());
|
||||
assertThat(tokenIntrospectionResponse.getIssuer()).isEqualTo(accessTokenClaims.getIssuer());
|
||||
assertThat(tokenIntrospectionResponse.getId()).isEqualTo(accessTokenClaims.getId());
|
||||
}
|
||||
|
||||
private static MultiValueMap<String, String> getTokenIntrospectionRequestParameters(AbstractOAuth2Token token,
|
||||
OAuth2TokenType tokenType) {
|
||||
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
|
||||
@@ -225,11 +322,37 @@ public class OAuth2TokenIntrospectionTests {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private OAuth2TokenIntrospection readTokenIntrospectionResponse(MvcResult mvcResult) throws Exception {
|
||||
private static OAuth2TokenIntrospection readTokenIntrospectionResponse(MvcResult mvcResult) throws Exception {
|
||||
MockHttpServletResponse servletResponse = mvcResult.getResponse();
|
||||
MockClientHttpResponse httpResponse = new MockClientHttpResponse(
|
||||
servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus()));
|
||||
return this.tokenIntrospectionHttpResponseConverter.read(OAuth2TokenIntrospection.class, httpResponse);
|
||||
return tokenIntrospectionHttpResponseConverter.read(OAuth2TokenIntrospection.class, httpResponse);
|
||||
}
|
||||
|
||||
private static MultiValueMap<String, String> getAuthorizationCodeTokenRequestParameters(RegisteredClient registeredClient,
|
||||
OAuth2Authorization authorization) {
|
||||
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
|
||||
parameters.set(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue());
|
||||
parameters.set(OAuth2ParameterNames.CODE, authorization.getToken(OAuth2AuthorizationCode.class).getToken().getTokenValue());
|
||||
parameters.set(OAuth2ParameterNames.REDIRECT_URI, registeredClient.getRedirectUris().iterator().next());
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static OAuth2AccessTokenResponse readAccessTokenResponse(MvcResult mvcResult) throws Exception {
|
||||
MockHttpServletResponse servletResponse = mvcResult.getResponse();
|
||||
MockClientHttpResponse httpResponse = new MockClientHttpResponse(
|
||||
servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus()));
|
||||
return accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
|
||||
}
|
||||
|
||||
private static String getAuthorizationHeader(RegisteredClient registeredClient) throws Exception {
|
||||
String clientId = registeredClient.getClientId();
|
||||
String clientSecret = registeredClient.getClientSecret();
|
||||
clientId = URLEncoder.encode(clientId, StandardCharsets.UTF_8.name());
|
||||
clientSecret = URLEncoder.encode(clientSecret, StandardCharsets.UTF_8.name());
|
||||
String credentialsString = clientId + ":" + clientSecret;
|
||||
byte[] encodedBytes = Base64.getEncoder().encode(credentialsString.getBytes(StandardCharsets.UTF_8));
|
||||
return "Basic " + new String(encodedBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@@ -244,6 +367,11 @@ public class OAuth2TokenIntrospectionTests {
|
||||
return authorizationService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
OAuth2AuthorizationConsentService authorizationConsentService(JdbcOperations jdbcOperations, RegisteredClientRepository registeredClientRepository) {
|
||||
return new JdbcOAuth2AuthorizationConsentService(jdbcOperations, registeredClientRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
|
||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
|
||||
@@ -259,13 +387,13 @@ public class OAuth2TokenIntrospectionTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
JWKSource<SecurityContext> jwkSource() {
|
||||
return jwkSource;
|
||||
ProviderSettings providerSettings() {
|
||||
return providerSettings;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ProviderSettings providerSettings() {
|
||||
return providerSettings;
|
||||
OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer() {
|
||||
return accessTokenCustomizer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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.core;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2TokenClaimsSet}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2TokenClaimsSetTests {
|
||||
|
||||
@Test
|
||||
public void buildWhenClaimsEmptyThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2TokenClaimsSet.builder().build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("claims cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenAllClaimsProvidedThenAllClaimsAreSet() {
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
|
||||
String customClaimName = "custom-claim-name";
|
||||
String customClaimValue = "custom-claim-value";
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenClaimsSet expectedClaimsSet = OAuth2TokenClaimsSet.builder()
|
||||
.issuer("https://provider.com")
|
||||
.subject("subject")
|
||||
.audience(Collections.singletonList("client-1"))
|
||||
.issuedAt(issuedAt)
|
||||
.notBefore(issuedAt)
|
||||
.expiresAt(expiresAt)
|
||||
.id("id")
|
||||
.claims(claims -> claims.put(customClaimName, customClaimValue))
|
||||
.build();
|
||||
|
||||
OAuth2TokenClaimsSet claimsSet = OAuth2TokenClaimsSet.builder()
|
||||
.issuer(expectedClaimsSet.getIssuer().toExternalForm())
|
||||
.subject(expectedClaimsSet.getSubject())
|
||||
.audience(expectedClaimsSet.getAudience())
|
||||
.issuedAt(expectedClaimsSet.getIssuedAt())
|
||||
.notBefore(expectedClaimsSet.getNotBefore())
|
||||
.expiresAt(expectedClaimsSet.getExpiresAt())
|
||||
.id(expectedClaimsSet.getId())
|
||||
.claims(claims -> claims.put(customClaimName, expectedClaimsSet.getClaim(customClaimName)))
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(claimsSet.getIssuer()).isEqualTo(expectedClaimsSet.getIssuer());
|
||||
assertThat(claimsSet.getSubject()).isEqualTo(expectedClaimsSet.getSubject());
|
||||
assertThat(claimsSet.getAudience()).isEqualTo(expectedClaimsSet.getAudience());
|
||||
assertThat(claimsSet.getIssuedAt()).isEqualTo(expectedClaimsSet.getIssuedAt());
|
||||
assertThat(claimsSet.getNotBefore()).isEqualTo(expectedClaimsSet.getNotBefore());
|
||||
assertThat(claimsSet.getExpiresAt()).isEqualTo(expectedClaimsSet.getExpiresAt());
|
||||
assertThat(claimsSet.getId()).isEqualTo(expectedClaimsSet.getId());
|
||||
assertThat(claimsSet.<String>getClaim(customClaimName)).isEqualTo(expectedClaimsSet.getClaim(customClaimName));
|
||||
assertThat(claimsSet.getClaims()).isEqualTo(expectedClaimsSet.getClaims());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void claimWhenNameNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2TokenClaimsSet.builder().claim(null, "value"))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("name cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void claimWhenValueNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2TokenClaimsSet.builder().claim("name", null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("value cannot be null");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
||||
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.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -99,6 +101,24 @@ public class JwtGeneratorTests {
|
||||
assertThat(this.jwtGenerator.generate(tokenContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateWhenUnsupportedTokenFormatThenReturnNull() {
|
||||
// @formatter:off
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(new OAuth2TokenFormat("unsupported_token_format"))
|
||||
.build();
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(tokenSettings)
|
||||
.build();
|
||||
OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(this.jwtGenerator.generate(tokenContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateWhenAccessTokenTypeThenReturnJwt() {
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenClaimAccessor;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||
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.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2AccessTokenGenerator}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2AccessTokenGeneratorTests {
|
||||
private OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private OAuth2AccessTokenGenerator accessTokenGenerator;
|
||||
private ProviderContext providerContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
this.accessTokenGenerator = new OAuth2AccessTokenGenerator();
|
||||
this.accessTokenGenerator.setAccessTokenCustomizer(this.accessTokenCustomizer);
|
||||
ProviderSettings providerSettings = ProviderSettings.builder().issuer("https://provider.com").build();
|
||||
this.providerContext = new ProviderContext(providerSettings, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAccessTokenCustomizerWhenNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> this.accessTokenGenerator.setAccessTokenCustomizer(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("accessTokenCustomizer cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateWhenUnsupportedTokenTypeThenReturnNull() {
|
||||
// @formatter:off
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build();
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(tokenSettings)
|
||||
.build();
|
||||
OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
.tokenType(new OAuth2TokenType("unsupported_token_type"))
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(this.accessTokenGenerator.generate(tokenContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateWhenUnsupportedTokenFormatThenReturnNull() {
|
||||
// @formatter:off
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(new OAuth2TokenFormat("unsupported_token_format"))
|
||||
.build();
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(tokenSettings)
|
||||
.build();
|
||||
OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(this.accessTokenGenerator.generate(tokenContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateWhenReferenceAccessTokenTypeThenReturnAccessToken() {
|
||||
// @formatter:off
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build();
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(tokenSettings)
|
||||
.build();
|
||||
// @formatter:on
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
Authentication principal = authorization.getAttribute(Principal.class.getName());
|
||||
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken("code", clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
.principal(principal)
|
||||
.providerContext(this.providerContext)
|
||||
.authorization(authorization)
|
||||
.authorizedScopes(authorization.getAttribute(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME))
|
||||
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.authorizationGrant(authentication)
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
OAuth2AccessToken accessToken = this.accessTokenGenerator.generate(tokenContext);
|
||||
assertThat(accessToken).isNotNull();
|
||||
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(tokenContext.getRegisteredClient().getTokenSettings().getAccessTokenTimeToLive());
|
||||
assertThat(accessToken.getIssuedAt()).isBetween(issuedAt.minusSeconds(1), issuedAt.plusSeconds(1));
|
||||
assertThat(accessToken.getExpiresAt()).isBetween(expiresAt.minusSeconds(1), expiresAt.plusSeconds(1));
|
||||
assertThat(accessToken.getScopes()).isEqualTo(tokenContext.getAuthorizedScopes());
|
||||
|
||||
assertThat(accessToken).isInstanceOf(ClaimAccessor.class);
|
||||
OAuth2TokenClaimAccessor accessTokenClaims = ((ClaimAccessor) accessToken)::getClaims;
|
||||
assertThat(accessTokenClaims.getClaims()).isNotEmpty();
|
||||
|
||||
assertThat(accessTokenClaims.getIssuer().toExternalForm()).isEqualTo(tokenContext.getProviderContext().getIssuer());
|
||||
assertThat(accessTokenClaims.getSubject()).isEqualTo(tokenContext.getPrincipal().getName());
|
||||
assertThat(accessTokenClaims.getAudience()).isEqualTo(
|
||||
Collections.singletonList(tokenContext.getRegisteredClient().getClientId()));
|
||||
assertThat(accessTokenClaims.getIssuedAt()).isBetween(issuedAt.minusSeconds(1), issuedAt.plusSeconds(1));
|
||||
assertThat(accessTokenClaims.getExpiresAt()).isBetween(expiresAt.minusSeconds(1), expiresAt.plusSeconds(1));
|
||||
assertThat(accessTokenClaims.getNotBefore()).isBetween(issuedAt.minusSeconds(1), issuedAt.plusSeconds(1));
|
||||
assertThat(accessTokenClaims.getId()).isNotNull();
|
||||
|
||||
Set<String> scopes = accessTokenClaims.getClaim(OAuth2ParameterNames.SCOPE);
|
||||
assertThat(scopes).isEqualTo(tokenContext.getAuthorizedScopes());
|
||||
|
||||
ArgumentCaptor<OAuth2TokenClaimsContext> tokenClaimsContextCaptor = ArgumentCaptor.forClass(OAuth2TokenClaimsContext.class);
|
||||
verify(this.accessTokenCustomizer).customize(tokenClaimsContextCaptor.capture());
|
||||
|
||||
OAuth2TokenClaimsContext tokenClaimsContext = tokenClaimsContextCaptor.getValue();
|
||||
assertThat(tokenClaimsContext.getClaims()).isNotNull();
|
||||
assertThat(tokenClaimsContext.getRegisteredClient()).isEqualTo(tokenContext.getRegisteredClient());
|
||||
assertThat(tokenClaimsContext.<Authentication>getPrincipal()).isEqualTo(tokenContext.getPrincipal());
|
||||
assertThat(tokenClaimsContext.getProviderContext()).isEqualTo(tokenContext.getProviderContext());
|
||||
assertThat(tokenClaimsContext.getAuthorization()).isEqualTo(tokenContext.getAuthorization());
|
||||
assertThat(tokenClaimsContext.getAuthorizedScopes()).isEqualTo(tokenContext.getAuthorizedScopes());
|
||||
assertThat(tokenClaimsContext.getTokenType()).isEqualTo(tokenContext.getTokenType());
|
||||
assertThat(tokenClaimsContext.getAuthorizationGrantType()).isEqualTo(tokenContext.getAuthorizationGrantType());
|
||||
assertThat(tokenClaimsContext.<Authentication>getAuthorizationGrant()).isEqualTo(tokenContext.getAuthorizationGrant());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenClaimsSet;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
|
||||
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.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2TokenClaimsContext}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OAuth2TokenClaimsContextTests {
|
||||
|
||||
@Test
|
||||
public void withWhenClaimsNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> OAuth2TokenClaimsContext.with(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("claimsBuilder cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
|
||||
String issuer = "https://provider.com";
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenClaimsSet.Builder claims = OAuth2TokenClaimsSet.builder()
|
||||
.issuer(issuer)
|
||||
.subject("subject")
|
||||
.audience(Collections.singletonList("client-1"))
|
||||
.issuedAt(issuedAt)
|
||||
.notBefore(issuedAt)
|
||||
.expiresAt(expiresAt)
|
||||
.id("id");
|
||||
// @formatter:on
|
||||
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
Authentication principal = authorization.getAttribute(Principal.class.getName());
|
||||
ProviderSettings providerSettings = ProviderSettings.builder().issuer(issuer).build();
|
||||
ProviderContext providerContext = new ProviderContext(providerSettings, null);
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authorizationGrant =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
"code", clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenClaimsContext context = OAuth2TokenClaimsContext.with(claims)
|
||||
.registeredClient(registeredClient)
|
||||
.principal(principal)
|
||||
.providerContext(providerContext)
|
||||
.authorization(authorization)
|
||||
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.authorizationGrant(authorizationGrant)
|
||||
.put("custom-key-1", "custom-value-1")
|
||||
.context(ctx -> ctx.put("custom-key-2", "custom-value-2"))
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(context.getClaims()).isEqualTo(claims);
|
||||
assertThat(context.getRegisteredClient()).isEqualTo(registeredClient);
|
||||
assertThat(context.<Authentication>getPrincipal()).isEqualTo(principal);
|
||||
assertThat(context.getProviderContext()).isEqualTo(providerContext);
|
||||
assertThat(context.getAuthorization()).isEqualTo(authorization);
|
||||
assertThat(context.getTokenType()).isEqualTo(OAuth2TokenType.ACCESS_TOKEN);
|
||||
assertThat(context.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
|
||||
assertThat(context.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authorizationGrant);
|
||||
assertThat(context.<String>get("custom-key-1")).isEqualTo("custom-value-1");
|
||||
assertThat(context.<String>get("custom-key-2")).isEqualTo("custom-value-2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.OAuth2Token;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
@@ -52,9 +53,11 @@ import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.server.authorization.DelegatingOAuth2TokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AccessTokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2RefreshTokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenClaimsContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenGenerator;
|
||||
@@ -90,6 +93,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
private OAuth2AuthorizationService authorizationService;
|
||||
private JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
||||
private OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private OAuth2TokenGenerator<?> tokenGenerator;
|
||||
private OAuth2AuthorizationCodeAuthenticationProvider authenticationProvider;
|
||||
|
||||
@@ -100,9 +104,12 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
this.jwtCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
JwtGenerator jwtGenerator = new JwtGenerator(this.jwtEncoder);
|
||||
jwtGenerator.setJwtCustomizer(this.jwtCustomizer);
|
||||
this.accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
|
||||
accessTokenGenerator.setAccessTokenCustomizer(this.accessTokenCustomizer);
|
||||
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
|
||||
OAuth2TokenGenerator<OAuth2Token> delegatingTokenGenerator =
|
||||
new DelegatingOAuth2TokenGenerator(jwtGenerator, refreshTokenGenerator);
|
||||
new DelegatingOAuth2TokenGenerator(jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
|
||||
this.tokenGenerator = spy(new OAuth2TokenGenerator<OAuth2Token>() {
|
||||
@Override
|
||||
public OAuth2Token generate(OAuth2TokenContext context) {
|
||||
@@ -312,8 +319,6 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
|
||||
|
||||
doAnswer(answer -> {
|
||||
OAuth2TokenContext context = answer.getArgument(0);
|
||||
if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
|
||||
@@ -686,6 +691,31 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
assertThat(accessTokenAuthentication.getRefreshToken().getTokenValue()).isEqualTo(refreshTokenGenerator.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenAccessTokenFormatReferenceThenAccessTokenGeneratorCalled() {
|
||||
// @formatter:off
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build())
|
||||
.build();
|
||||
// @formatter:on
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
|
||||
.thenReturn(authorization);
|
||||
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
this.authenticationProvider.authenticate(authentication);
|
||||
|
||||
verify(this.accessTokenCustomizer).customize(any());
|
||||
}
|
||||
|
||||
private static Jwt createJwt() {
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
|
||||
|
||||
@@ -31,22 +31,28 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.OAuth2Token;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
|
||||
import org.springframework.security.oauth2.jwt.JoseHeaderNames;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.server.authorization.DelegatingOAuth2TokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AccessTokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenClaimsContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenGenerator;
|
||||
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.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
|
||||
import org.springframework.security.oauth2.server.authorization.context.ProviderContextHolder;
|
||||
|
||||
@@ -69,6 +75,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
private OAuth2AuthorizationService authorizationService;
|
||||
private JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
||||
private OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private OAuth2TokenGenerator<?> tokenGenerator;
|
||||
private OAuth2ClientCredentialsAuthenticationProvider authenticationProvider;
|
||||
|
||||
@@ -79,10 +86,15 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
this.jwtCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
JwtGenerator jwtGenerator = new JwtGenerator(this.jwtEncoder);
|
||||
jwtGenerator.setJwtCustomizer(this.jwtCustomizer);
|
||||
this.tokenGenerator = spy(new OAuth2TokenGenerator<Jwt>() {
|
||||
this.accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
|
||||
accessTokenGenerator.setAccessTokenCustomizer(this.accessTokenCustomizer);
|
||||
OAuth2TokenGenerator<OAuth2Token> delegatingTokenGenerator =
|
||||
new DelegatingOAuth2TokenGenerator(jwtGenerator, accessTokenGenerator);
|
||||
this.tokenGenerator = spy(new OAuth2TokenGenerator<OAuth2Token>() {
|
||||
@Override
|
||||
public Jwt generate(OAuth2TokenContext context) {
|
||||
return jwtGenerator.generate(context);
|
||||
public OAuth2Token generate(OAuth2TokenContext context) {
|
||||
return delegatingTokenGenerator.generate(context);
|
||||
}
|
||||
});
|
||||
this.authenticationProvider = new OAuth2ClientCredentialsAuthenticationProvider(
|
||||
@@ -275,6 +287,25 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(authorization.getAccessToken().getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenAccessTokenFormatReferenceThenAccessTokenGeneratorCalled() {
|
||||
// @formatter:off
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2()
|
||||
.tokenSettings(TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build())
|
||||
.build();
|
||||
// @formatter:on
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
|
||||
this.authenticationProvider.authenticate(authentication);
|
||||
|
||||
verify(this.accessTokenCustomizer).customize(any());
|
||||
}
|
||||
|
||||
private static Jwt createJwt(Set<String> scope) {
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2Token;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
@@ -50,9 +51,11 @@ import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.server.authorization.DelegatingOAuth2TokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AccessTokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2RefreshTokenGenerator;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenClaimsContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenGenerator;
|
||||
@@ -88,6 +91,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
private OAuth2AuthorizationService authorizationService;
|
||||
private JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
|
||||
private OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
|
||||
private OAuth2TokenGenerator<?> tokenGenerator;
|
||||
private OAuth2RefreshTokenAuthenticationProvider authenticationProvider;
|
||||
|
||||
@@ -99,9 +103,12 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
this.jwtCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
JwtGenerator jwtGenerator = new JwtGenerator(this.jwtEncoder);
|
||||
jwtGenerator.setJwtCustomizer(this.jwtCustomizer);
|
||||
this.accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
|
||||
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
|
||||
accessTokenGenerator.setAccessTokenCustomizer(this.accessTokenCustomizer);
|
||||
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
|
||||
OAuth2TokenGenerator<OAuth2Token> delegatingTokenGenerator =
|
||||
new DelegatingOAuth2TokenGenerator(jwtGenerator, refreshTokenGenerator);
|
||||
new DelegatingOAuth2TokenGenerator(jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
|
||||
this.tokenGenerator = spy(new OAuth2TokenGenerator<OAuth2Token>() {
|
||||
@Override
|
||||
public OAuth2Token generate(OAuth2TokenContext context) {
|
||||
@@ -623,6 +630,31 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenAccessTokenFormatReferenceThenAccessTokenGeneratorCalled() {
|
||||
// @formatter:off
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build())
|
||||
.build();
|
||||
// @formatter:on
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(
|
||||
eq(authorization.getRefreshToken().getToken().getTokenValue()),
|
||||
eq(OAuth2TokenType.REFRESH_TOKEN)))
|
||||
.thenReturn(authorization);
|
||||
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
this.authenticationProvider.authenticate(authentication);
|
||||
|
||||
verify(this.accessTokenCustomizer).customize(any());
|
||||
}
|
||||
|
||||
private static Jwt createJwt(Set<String> scope) {
|
||||
Instant issuedAt = Instant.now();
|
||||
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2022 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.
|
||||
@@ -31,10 +31,9 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenClaimsSet;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospection;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
|
||||
import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
@@ -189,7 +188,7 @@ public class OAuth2TokenIntrospectionAuthenticationProviderTests {
|
||||
Instant expiresAt = issuedAt.plus(Duration.ofHours(1));
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
OAuth2AccessToken.TokenType.BEARER, "access-token", issuedAt, expiresAt);
|
||||
Map<String, Object> accessTokenClaims = Collections.singletonMap(JwtClaimNames.NBF, notBefore);
|
||||
Map<String, Object> accessTokenClaims = Collections.singletonMap(OAuth2TokenClaimNames.NBF, notBefore);
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations
|
||||
.authorization(registeredClient, accessToken, accessTokenClaims)
|
||||
.build();
|
||||
@@ -217,9 +216,21 @@ public class OAuth2TokenIntrospectionAuthenticationProviderTests {
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
OAuth2AccessToken.TokenType.BEARER, "access-token", issuedAt, expiresAt,
|
||||
new HashSet<>(Arrays.asList("scope1", "scope2")));
|
||||
JwtClaimsSet jwtClaims = TestJwtClaimsSets.jwtClaimsSet().build();
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenClaimsSet claimsSet = OAuth2TokenClaimsSet.builder()
|
||||
.issuer("https://provider.com")
|
||||
.subject("subject")
|
||||
.audience(Collections.singletonList(authorizedClient.getClientId()))
|
||||
.issuedAt(issuedAt)
|
||||
.notBefore(issuedAt)
|
||||
.expiresAt(expiresAt)
|
||||
.id("id")
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations
|
||||
.authorization(authorizedClient, accessToken, jwtClaims.getClaims())
|
||||
.authorization(authorizedClient, accessToken, claimsSet.getClaims())
|
||||
.build();
|
||||
when(this.authorizationService.findByToken(eq(accessToken.getTokenValue()), isNull()))
|
||||
.thenReturn(authorization);
|
||||
@@ -243,11 +254,11 @@ public class OAuth2TokenIntrospectionAuthenticationProviderTests {
|
||||
assertThat(tokenClaims.getExpiresAt()).isEqualTo(accessToken.getExpiresAt());
|
||||
assertThat(tokenClaims.getScopes()).containsExactlyInAnyOrderElementsOf(accessToken.getScopes());
|
||||
assertThat(tokenClaims.getTokenType()).isEqualTo(accessToken.getTokenType().getValue());
|
||||
assertThat(tokenClaims.getNotBefore()).isEqualTo(jwtClaims.getNotBefore());
|
||||
assertThat(tokenClaims.getSubject()).isEqualTo(jwtClaims.getSubject());
|
||||
assertThat(tokenClaims.getAudience()).containsExactlyInAnyOrderElementsOf(jwtClaims.getAudience());
|
||||
assertThat(tokenClaims.getIssuer()).isEqualTo(jwtClaims.getIssuer());
|
||||
assertThat(tokenClaims.getId()).isEqualTo(jwtClaims.getId());
|
||||
assertThat(tokenClaims.getNotBefore()).isEqualTo(claimsSet.getNotBefore());
|
||||
assertThat(tokenClaims.getSubject()).isEqualTo(claimsSet.getSubject());
|
||||
assertThat(tokenClaims.getAudience()).containsExactlyInAnyOrderElementsOf(claimsSet.getAudience());
|
||||
assertThat(tokenClaims.getIssuer()).isEqualTo(claimsSet.getIssuer());
|
||||
assertThat(tokenClaims.getId()).isEqualTo(claimsSet.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2022 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.
|
||||
@@ -19,6 +19,7 @@ import java.time.Duration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -34,8 +35,9 @@ public class TokenSettingsTests {
|
||||
@Test
|
||||
public void buildWhenDefaultThenDefaultsAreSet() {
|
||||
TokenSettings tokenSettings = TokenSettings.builder().build();
|
||||
assertThat(tokenSettings.getSettings()).hasSize(4);
|
||||
assertThat(tokenSettings.getSettings()).hasSize(5);
|
||||
assertThat(tokenSettings.getAccessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5));
|
||||
assertThat(tokenSettings.getAccessTokenFormat()).isEqualTo(OAuth2TokenFormat.SELF_CONTAINED);
|
||||
assertThat(tokenSettings.isReuseRefreshTokens()).isTrue();
|
||||
assertThat(tokenSettings.getRefreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
|
||||
assertThat(tokenSettings.getIdTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
|
||||
@@ -68,6 +70,22 @@ public class TokenSettingsTests {
|
||||
.isEqualTo("accessTokenTimeToLive must be greater than Duration.ZERO");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessTokenFormatWhenProvidedThenSet() {
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
|
||||
.build();
|
||||
assertThat(tokenSettings.getAccessTokenFormat()).isEqualTo(OAuth2TokenFormat.REFERENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessTokenFormatWhenNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> TokenSettings.builder().accessTokenFormat(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.extracting(Throwable::getMessage)
|
||||
.isEqualTo("accessTokenFormat cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reuseRefreshTokensWhenFalseThenSet() {
|
||||
TokenSettings tokenSettings = TokenSettings.builder()
|
||||
@@ -118,7 +136,7 @@ public class TokenSettingsTests {
|
||||
.setting("name1", "value1")
|
||||
.settings(settings -> settings.put("name2", "value2"))
|
||||
.build();
|
||||
assertThat(tokenSettings.getSettings()).hasSize(6);
|
||||
assertThat(tokenSettings.getSettings()).hasSize(7);
|
||||
assertThat(tokenSettings.<String>getSetting("name1")).isEqualTo("value1");
|
||||
assertThat(tokenSettings.<String>getSetting("name2")).isEqualTo("value2");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user