Introduce OAuth2Tokens

Closes gh-137
This commit is contained in:
Joe Grandja
2020-10-19 08:12:45 -04:00
parent 7b1b965c08
commit af60f3d4d0
14 changed files with 774 additions and 24 deletions

View File

@@ -20,6 +20,7 @@ import org.junit.Test;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
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.token.OAuth2Tokens;
import java.time.Instant;
@@ -129,7 +130,7 @@ public class InMemoryOAuth2AuthorizationServiceTests {
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
.principalName(PRINCIPAL_NAME)
.attribute(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE)
.accessToken(accessToken)
.tokens(OAuth2Tokens.builder().accessToken(accessToken).build())
.build();
this.authorizationService.save(authorization);

View File

@@ -19,6 +19,7 @@ import org.junit.Test;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
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.token.OAuth2Tokens;
import java.time.Instant;
@@ -57,14 +58,14 @@ public class OAuth2AuthorizationTests {
public void fromWhenAuthorizationProvidedThenCopied() {
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
.principalName(PRINCIPAL_NAME)
.accessToken(ACCESS_TOKEN)
.tokens(OAuth2Tokens.builder().accessToken(ACCESS_TOKEN).build())
.attribute(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE)
.build();
OAuth2Authorization authorizationResult = OAuth2Authorization.from(authorization).build();
assertThat(authorizationResult.getRegisteredClientId()).isEqualTo(authorization.getRegisteredClientId());
assertThat(authorizationResult.getPrincipalName()).isEqualTo(authorization.getPrincipalName());
assertThat(authorizationResult.getAccessToken()).isEqualTo(authorization.getAccessToken());
assertThat(authorizationResult.getTokens().getAccessToken()).isEqualTo(authorization.getTokens().getAccessToken());
assertThat(authorizationResult.getAttributes()).isEqualTo(authorization.getAttributes());
}
@@ -97,13 +98,13 @@ public class OAuth2AuthorizationTests {
public void buildWhenAllAttributesAreProvidedThenAllAttributesAreSet() {
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
.principalName(PRINCIPAL_NAME)
.accessToken(ACCESS_TOKEN)
.tokens(OAuth2Tokens.builder().accessToken(ACCESS_TOKEN).build())
.attribute(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE)
.build();
assertThat(authorization.getRegisteredClientId()).isEqualTo(REGISTERED_CLIENT.getId());
assertThat(authorization.getPrincipalName()).isEqualTo(PRINCIPAL_NAME);
assertThat(authorization.getAccessToken()).isEqualTo(ACCESS_TOKEN);
assertThat(authorization.getTokens().getAccessToken()).isEqualTo(ACCESS_TOKEN);
assertThat(authorization.getAttributes()).containsExactly(
entry(OAuth2AuthorizationAttributeNames.CODE, AUTHORIZATION_CODE));
}

View File

@@ -19,6 +19,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
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.token.OAuth2Tokens;
import java.time.Instant;
import java.util.Collections;
@@ -52,7 +53,7 @@ public class TestOAuth2Authorizations {
.build();
return OAuth2Authorization.withRegisteredClient(registeredClient)
.principalName("principal")
.accessToken(accessToken)
.tokens(OAuth2Tokens.builder().accessToken(accessToken).build())
.attribute(OAuth2AuthorizationAttributeNames.CODE, "code")
.attribute(OAuth2AuthorizationAttributeNames.AUTHORIZATION_REQUEST, authorizationRequest)
.attribute(OAuth2AuthorizationAttributeNames.AUTHORIZED_SCOPES, authorizationRequest.getScopes());

View File

@@ -203,8 +203,8 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
assertThat(accessTokenAuthentication.getRegisteredClient().getId()).isEqualTo(updatedAuthorization.getRegisteredClientId());
assertThat(accessTokenAuthentication.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(updatedAuthorization.getAccessToken()).isNotNull();
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(updatedAuthorization.getAccessToken());
assertThat(updatedAuthorization.getTokens().getAccessToken()).isNotNull();
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(updatedAuthorization.getTokens().getAccessToken());
}
private static Jwt createJwt() {

View File

@@ -156,10 +156,10 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
assertThat(authorization.getRegisteredClientId()).isEqualTo(clientPrincipal.getRegisteredClient().getId());
assertThat(authorization.getPrincipalName()).isEqualTo(clientPrincipal.getName());
assertThat(authorization.getAccessToken()).isNotNull();
assertThat(authorization.getAccessToken().getScopes()).isEqualTo(clientPrincipal.getRegisteredClient().getScopes());
assertThat(authorization.getTokens().getAccessToken()).isNotNull();
assertThat(authorization.getTokens().getAccessToken().getScopes()).isEqualTo(clientPrincipal.getRegisteredClient().getScopes());
assertThat(accessTokenAuthentication.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(authorization.getAccessToken());
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(authorization.getTokens().getAccessToken());
}
private static Jwt createJwt() {

View File

@@ -0,0 +1,74 @@
/*
* 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.token;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link OAuth2TokenMetadata}.
*
* @author Joe Grandja
*/
public class OAuth2TokenMetadataTests {
@Test
public void metadataWhenNameNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() ->
OAuth2TokenMetadata.builder()
.metadata(null, "value"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("name cannot be empty");
}
@Test
public void metadataWhenValueNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() ->
OAuth2TokenMetadata.builder()
.metadata("name", null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("value cannot be null");
}
@Test
public void getMetadataWhenNameNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2TokenMetadata.builder().build().getMetadata(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("name cannot be empty");
}
@Test
public void buildWhenDefaultThenDefaultsAreSet() {
OAuth2TokenMetadata tokenMetadata = OAuth2TokenMetadata.builder().build();
assertThat(tokenMetadata.getMetadata()).hasSize(1);
assertThat(tokenMetadata.isInvalidated()).isFalse();
}
@Test
public void buildWhenMetadataProvidedThenMetadataIsSet() {
OAuth2TokenMetadata tokenMetadata = OAuth2TokenMetadata.builder()
.invalidated()
.metadata("name1", "value1")
.metadata(metadata -> metadata.put("name2", "value2"))
.build();
assertThat(tokenMetadata.getMetadata()).hasSize(3);
assertThat(tokenMetadata.isInvalidated()).isTrue();
assertThat(tokenMetadata.<String>getMetadata("name1")).isEqualTo("value1");
assertThat(tokenMetadata.<String>getMetadata("name2")).isEqualTo("value2");
}
}

View File

@@ -0,0 +1,187 @@
/*
* 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.token;
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashSet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link OAuth2Tokens}.
*
* @author Joe Grandja
*/
public class OAuth2TokensTests {
private OAuth2AccessToken accessToken;
private OAuth2RefreshToken refreshToken;
private OidcIdToken idToken;
@Before
public void setUp() {
Instant issuedAt = Instant.now();
this.accessToken = new OAuth2AccessToken(
OAuth2AccessToken.TokenType.BEARER,
"access-token",
issuedAt,
issuedAt.plus(Duration.ofMinutes(5)),
new HashSet<>(Arrays.asList("read", "write")));
this.refreshToken = new OAuth2RefreshToken(
"refresh-token",
issuedAt);
this.idToken = OidcIdToken.withTokenValue("id-token")
.issuer("https://provider.com")
.subject("subject")
.issuedAt(issuedAt)
.expiresAt(issuedAt.plus(Duration.ofMinutes(30)))
.build();
}
@Test
public void accessTokenWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2Tokens.builder().accessToken(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("token cannot be null");
}
@Test
public void refreshTokenWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2Tokens.builder().refreshToken(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("token cannot be null");
}
@Test
public void tokenWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2Tokens.builder().token(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("token cannot be null");
}
@Test
public void getTokenWhenTokenTypeNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2Tokens.builder().build().getToken(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("tokenType cannot be null");
}
@Test
public void getTokenMetadataWhenTokenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> OAuth2Tokens.builder().build().getTokenMetadata(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("token cannot be null");
}
@Test
public void buildWhenTokenMetadataNotProvidedThenDefaultsAreSet() {
OAuth2Tokens tokens = OAuth2Tokens.builder()
.accessToken(this.accessToken)
.refreshToken(this.refreshToken)
.token(this.idToken)
.build();
assertThat(tokens.getAccessToken()).isEqualTo(this.accessToken);
OAuth2TokenMetadata tokenMetadata = tokens.getTokenMetadata(tokens.getAccessToken());
assertThat(tokenMetadata.isInvalidated()).isFalse();
assertThat(tokens.getRefreshToken()).isEqualTo(this.refreshToken);
tokenMetadata = tokens.getTokenMetadata(tokens.getRefreshToken());
assertThat(tokenMetadata.isInvalidated()).isFalse();
assertThat(tokens.getToken(OidcIdToken.class)).isEqualTo(this.idToken);
tokenMetadata = tokens.getTokenMetadata(tokens.getToken(OidcIdToken.class));
assertThat(tokenMetadata.isInvalidated()).isFalse();
}
@Test
public void buildWhenTokenMetadataProvidedThenTokenMetadataIsSet() {
OAuth2TokenMetadata expectedTokenMetadata = OAuth2TokenMetadata.builder().build();
OAuth2Tokens tokens = OAuth2Tokens.builder()
.accessToken(this.accessToken, expectedTokenMetadata)
.refreshToken(this.refreshToken, expectedTokenMetadata)
.token(this.idToken, expectedTokenMetadata)
.build();
assertThat(tokens.getAccessToken()).isEqualTo(this.accessToken);
OAuth2TokenMetadata tokenMetadata = tokens.getTokenMetadata(tokens.getAccessToken());
assertThat(tokenMetadata).isEqualTo(expectedTokenMetadata);
assertThat(tokens.getRefreshToken()).isEqualTo(this.refreshToken);
tokenMetadata = tokens.getTokenMetadata(tokens.getRefreshToken());
assertThat(tokenMetadata).isEqualTo(expectedTokenMetadata);
assertThat(tokens.getToken(OidcIdToken.class)).isEqualTo(this.idToken);
tokenMetadata = tokens.getTokenMetadata(tokens.getToken(OidcIdToken.class));
assertThat(tokenMetadata).isEqualTo(expectedTokenMetadata);
}
@Test
public void getTokenMetadataWhenTokenNotFoundThenNull() {
OAuth2TokenMetadata expectedTokenMetadata = OAuth2TokenMetadata.builder().build();
OAuth2Tokens tokens = OAuth2Tokens.builder()
.accessToken(this.accessToken, expectedTokenMetadata)
.build();
assertThat(tokens.getAccessToken()).isEqualTo(this.accessToken);
OAuth2TokenMetadata tokenMetadata = tokens.getTokenMetadata(tokens.getAccessToken());
assertThat(tokenMetadata).isEqualTo(expectedTokenMetadata);
OAuth2AccessToken otherAccessToken = new OAuth2AccessToken(
this.accessToken.getTokenType(),
"other-access-token",
this.accessToken.getIssuedAt(),
this.accessToken.getExpiresAt(),
this.accessToken.getScopes());
assertThat(tokens.getTokenMetadata(otherAccessToken)).isNull();
}
@Test
public void invalidateWhenAllTokensThenAllInvalidated() {
OAuth2Tokens tokens = OAuth2Tokens.builder()
.accessToken(this.accessToken)
.refreshToken(this.refreshToken)
.token(this.idToken)
.build();
tokens.invalidate();
assertThat(tokens.getTokenMetadata(tokens.getAccessToken()).isInvalidated()).isTrue();
assertThat(tokens.getTokenMetadata(tokens.getRefreshToken()).isInvalidated()).isTrue();
assertThat(tokens.getTokenMetadata(tokens.getToken(OidcIdToken.class)).isInvalidated()).isTrue();
}
@Test
public void invalidateWhenTokenProvidedThenInvalidated() {
OAuth2Tokens tokens = OAuth2Tokens.builder()
.accessToken(this.accessToken)
.refreshToken(this.refreshToken)
.token(this.idToken)
.build();
tokens.invalidate(this.accessToken);
assertThat(tokens.getTokenMetadata(tokens.getAccessToken()).isInvalidated()).isTrue();
assertThat(tokens.getTokenMetadata(tokens.getRefreshToken()).isInvalidated()).isFalse();
assertThat(tokens.getTokenMetadata(tokens.getToken(OidcIdToken.class)).isInvalidated()).isFalse();
}
}

View File

@@ -755,7 +755,7 @@ public class OAuth2AuthorizationEndpointFilterTests {
OAuth2Authorization updatedAuthorization = authorizationCaptor.getValue();
assertThat(updatedAuthorization.getRegisteredClientId()).isEqualTo(registeredClient.getId());
assertThat(updatedAuthorization.getPrincipalName()).isEqualTo(this.authentication.getPrincipal().toString());
assertThat(updatedAuthorization.getAccessToken()).isNotNull();
assertThat(updatedAuthorization.getTokens().getAccessToken()).isNotNull();
assertThat(updatedAuthorization.<String>getAttribute(OAuth2AuthorizationAttributeNames.STATE)).isNull();
assertThat(updatedAuthorization.<String>getAttribute(OAuth2AuthorizationAttributeNames.CODE)).isNotNull();
assertThat(updatedAuthorization.<OAuth2AuthorizationRequest>getAttribute(OAuth2AuthorizationAttributeNames.AUTHORIZATION_REQUEST))