Use TokenSettings.accessTokenTimeToLive()

Closes gh-172
This commit is contained in:
Joe Grandja 2020-12-08 05:58:43 -05:00
parent 79f1cf5a50
commit f077337e43
5 changed files with 23 additions and 11 deletions

View File

@ -118,7 +118,7 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica
Set<String> authorizedScopes = authorization.getAttribute(OAuth2AuthorizationAttributeNames.AUTHORIZED_SCOPES); Set<String> authorizedScopes = authorization.getAttribute(OAuth2AuthorizationAttributeNames.AUTHORIZED_SCOPES);
Jwt jwt = OAuth2TokenIssuerUtil Jwt jwt = OAuth2TokenIssuerUtil
.issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), authorizedScopes); .issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), authorizedScopes, registeredClient.getTokenSettings().accessTokenTimeToLive());
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), authorizedScopes); jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), authorizedScopes);

View File

@ -94,7 +94,7 @@ public class OAuth2ClientCredentialsAuthenticationProvider implements Authentica
} }
Jwt jwt = OAuth2TokenIssuerUtil Jwt jwt = OAuth2TokenIssuerUtil
.issueJwtAccessToken(this.jwtEncoder, clientPrincipal.getName(), registeredClient.getClientId(), scopes); .issueJwtAccessToken(this.jwtEncoder, clientPrincipal.getName(), registeredClient.getClientId(), scopes, registeredClient.getTokenSettings().accessTokenTimeToLive());
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes); jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);

View File

@ -114,7 +114,7 @@ public class OAuth2RefreshTokenAuthenticationProvider implements AuthenticationP
} }
Jwt jwt = OAuth2TokenIssuerUtil Jwt jwt = OAuth2TokenIssuerUtil
.issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), scopes); .issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), scopes, registeredClient.getTokenSettings().accessTokenTimeToLive());
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes); jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);

View File

@ -28,7 +28,6 @@ import org.springframework.security.oauth2.jwt.JwtEncoder;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64; import java.util.Base64;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -41,12 +40,12 @@ class OAuth2TokenIssuerUtil {
private static final StringKeyGenerator TOKEN_GENERATOR = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); private static final StringKeyGenerator TOKEN_GENERATOR = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
static Jwt issueJwtAccessToken(JwtEncoder jwtEncoder, String subject, String audience, Set<String> scopes) { static Jwt issueJwtAccessToken(JwtEncoder jwtEncoder, String subject, String audience, Set<String> scopes, Duration tokenTimeToLive) {
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build(); JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
String issuer = "https://oauth2.provider.com"; // TODO Allow configuration for issuer claim String issuer = "https://oauth2.provider.com"; // TODO Allow configuration for issuer claim
Instant issuedAt = Instant.now(); Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token time-to-live Instant expiresAt = issuedAt.plus(tokenTimeToLive);
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder() JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder()
.issuer(issuer) .issuer(issuer)
@ -61,9 +60,9 @@ class OAuth2TokenIssuerUtil {
return jwtEncoder.encode(joseHeader, jwtClaimsSet); return jwtEncoder.encode(joseHeader, jwtClaimsSet);
} }
static OAuth2RefreshToken issueRefreshToken(Duration refreshTokenTimeToLive) { static OAuth2RefreshToken issueRefreshToken(Duration tokenTimeToLive) {
Instant issuedAt = Instant.now(); Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(refreshTokenTimeToLive); Instant expiresAt = issuedAt.plus(tokenTimeToLive);
return new OAuth2RefreshToken2(TOKEN_GENERATOR.generateKey(), issuedAt, expiresAt); return new OAuth2RefreshToken2(TOKEN_GENERATOR.generateKey(), issuedAt, expiresAt);
} }

View File

@ -251,10 +251,12 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
} }
@Test @Test
public void authenticateWhenRefreshTokenTimeToLiveConfiguredThenRefreshTokenExpirySet() { public void authenticateWhenTokenTimeToLiveConfiguredThenTokenExpirySet() {
Duration accessTokenTTL = Duration.ofHours(2);
Duration refreshTokenTTL = Duration.ofDays(1); Duration refreshTokenTTL = Duration.ofDays(1);
RegisteredClient registeredClient = TestRegisteredClients.registeredClient() RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.tokenSettings(tokenSettings -> tokenSettings.refreshTokenTimeToLive(refreshTokenTTL)) .tokenSettings(tokenSettings ->
tokenSettings.accessTokenTimeToLive(accessTokenTTL).refreshTokenTimeToLive(refreshTokenTTL))
.build(); .build();
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
@ -267,7 +269,9 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
OAuth2AuthorizationCodeAuthenticationToken authentication = OAuth2AuthorizationCodeAuthenticationToken authentication =
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null); new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt()); Instant accessTokenIssuedAt = Instant.now();
Instant accessTokenExpiresAt = accessTokenIssuedAt.plus(accessTokenTTL);
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(accessTokenIssuedAt, accessTokenExpiresAt));
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication); (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@ -276,6 +280,11 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
verify(this.authorizationService).save(authorizationCaptor.capture()); verify(this.authorizationService).save(authorizationCaptor.capture());
OAuth2Authorization updatedAuthorization = authorizationCaptor.getValue(); OAuth2Authorization updatedAuthorization = authorizationCaptor.getValue();
assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(updatedAuthorization.getTokens().getAccessToken());
Instant expectedAccessTokenExpiresAt = accessTokenAuthentication.getAccessToken().getIssuedAt().plus(accessTokenTTL);
assertThat(accessTokenAuthentication.getAccessToken().getExpiresAt()).isBetween(
expectedAccessTokenExpiresAt.minusSeconds(1), expectedAccessTokenExpiresAt.plusSeconds(1));
assertThat(accessTokenAuthentication.getRefreshToken()).isEqualTo(updatedAuthorization.getTokens().getRefreshToken()); assertThat(accessTokenAuthentication.getRefreshToken()).isEqualTo(updatedAuthorization.getTokens().getRefreshToken());
Instant expectedRefreshTokenExpiresAt = accessTokenAuthentication.getRefreshToken().getIssuedAt().plus(refreshTokenTTL); Instant expectedRefreshTokenExpiresAt = accessTokenAuthentication.getRefreshToken().getIssuedAt().plus(refreshTokenTTL);
assertThat(accessTokenAuthentication.getRefreshToken().getExpiresAt()).isBetween( assertThat(accessTokenAuthentication.getRefreshToken().getExpiresAt()).isBetween(
@ -309,6 +318,10 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
private static Jwt createJwt() { private static Jwt createJwt() {
Instant issuedAt = Instant.now(); Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS);
return createJwt(issuedAt, expiresAt);
}
private static Jwt createJwt(Instant issuedAt, Instant expiresAt) {
return Jwt.withTokenValue("token") return Jwt.withTokenValue("token")
.header(JoseHeaderNames.ALG, SignatureAlgorithm.RS256.getName()) .header(JoseHeaderNames.ALG, SignatureAlgorithm.RS256.getName())
.issuedAt(issuedAt) .issuedAt(issuedAt)