浏览代码

Add OAuth2AccessTokenResponse.withResponse

Add ability to build a new OAuth2AccessTokenResponse from another
OAuth2AccessTokenResponse.

Fixes: gh-5474
Rob Winch 7 年之前
父节点
当前提交
ab61732e17

+ 50 - 7
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponse.java

@@ -21,6 +21,7 @@ import org.springframework.security.oauth2.core.OAuth2RefreshToken;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
+import java.time.Duration;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.Map;
@@ -81,6 +82,15 @@ public final class OAuth2AccessTokenResponse {
 		return new Builder(tokenValue);
 	}
 
+	/**
+	 * Returns a new {@link Builder}, initialized with the provided response
+	 * @param response the response to intialize the builder with
+	 * @return the {@link Builder}
+	 */
+	public static Builder withResponse(OAuth2AccessTokenResponse response) {
+		return new Builder(response);
+	}
+
 	/**
 	 * A builder for {@link OAuth2AccessTokenResponse}.
 	 */
@@ -92,6 +102,21 @@ public final class OAuth2AccessTokenResponse {
 		private String refreshToken;
 		private Map<String, Object> additionalParameters;
 
+		private Instant issuedAt;
+		private Instant expiresAt;
+
+		private Builder(OAuth2AccessTokenResponse response) {
+			OAuth2AccessToken accessToken = response.getAccessToken();
+			this.tokenValue = accessToken.getTokenValue();
+			this.tokenType = accessToken.getTokenType();
+			this.expiresAt = accessToken.getExpiresAt();
+			this.issuedAt = accessToken.getIssuedAt();
+			this.scopes = accessToken.getScopes();
+			this.refreshToken = response.getRefreshToken() == null ?
+					null : response.getRefreshToken().getTokenValue();
+			this.additionalParameters = response.getAdditionalParameters();
+		}
+
 		private Builder(String tokenValue) {
 			this.tokenValue = tokenValue;
 		}
@@ -157,14 +182,9 @@ public final class OAuth2AccessTokenResponse {
 		 * @return a {@link OAuth2AccessTokenResponse}
 		 */
 		public OAuth2AccessTokenResponse build() {
-			Instant issuedAt = Instant.now();
+			Instant issuedAt = getIssuedAt();
 
-			// expires_in is RECOMMENDED, as per spec https://tools.ietf.org/html/rfc6749#section-5.1
-			// Therefore, expires_in may not be returned in the Access Token response which would result in the default value of 0.
-			// For these instances, default the expiresAt to +1 second from issuedAt time.
-			Instant expiresAt = this.expiresIn > 0 ?
-				issuedAt.plusSeconds(this.expiresIn) :
-				issuedAt.plusSeconds(1);
+			Instant expiresAt = getExpiresAt();
 
 			OAuth2AccessTokenResponse accessTokenResponse = new OAuth2AccessTokenResponse();
 			accessTokenResponse.accessToken = new OAuth2AccessToken(
@@ -181,5 +201,28 @@ public final class OAuth2AccessTokenResponse {
 				CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() : this.additionalParameters);
 			return accessTokenResponse;
 		}
+
+		private Instant getIssuedAt() {
+			if (this.issuedAt == null) {
+				this.issuedAt = Instant.now();
+			}
+			return this.issuedAt;
+		}
+
+		/**
+		 * expires_in is RECOMMENDED, as per spec https://tools.ietf.org/html/rfc6749#section-5.1
+		 * Therefore, expires_in may not be returned in the Access Token response which would result in the default value of 0.
+		 * For these instances, default the expiresAt to +1 second from issuedAt time.
+		 * @return
+		 */
+		private Instant getExpiresAt() {
+			if (this.expiresAt == null) {
+				Instant issuedAt = getIssuedAt();
+				this.expiresAt = this.expiresIn > 0 ?
+								issuedAt.plusSeconds(this.expiresIn) :
+								issuedAt.plusSeconds(1);
+			}
+			return this.expiresAt;
+		}
 	}
 }

+ 51 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java

@@ -102,4 +102,55 @@ public class OAuth2AccessTokenResponseTests {
 		assertThat(tokenResponse.getRefreshToken().getTokenValue()).isEqualTo(REFRESH_TOKEN_VALUE);
 		assertThat(tokenResponse.getAdditionalParameters()).isEqualTo(additionalParameters);
 	}
+
+	@Test
+	public void buildWhenResponseThenAllAttributesAreSet() {
+		Instant expiresAt = Instant.now().plusSeconds(5);
+		Set<String> scopes = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));
+		Map<String, Object> additionalParameters = new HashMap<>();
+		additionalParameters.put("param1", "value1");
+		additionalParameters.put("param2", "value2");
+
+		OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse
+				.withToken(TOKEN_VALUE)
+				.tokenType(OAuth2AccessToken.TokenType.BEARER)
+				.expiresIn(expiresAt.toEpochMilli())
+				.scopes(scopes)
+				.refreshToken(REFRESH_TOKEN_VALUE)
+				.additionalParameters(additionalParameters)
+				.build();
+
+		OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse)
+				.build();
+
+		assertThat(withResponse.getAccessToken().getTokenValue()).isEqualTo(tokenResponse.getAccessToken().getTokenValue());
+		assertThat(withResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
+		assertThat(withResponse.getAccessToken().getIssuedAt()).isEqualTo(tokenResponse.getAccessToken().getIssuedAt());
+		assertThat(withResponse.getAccessToken().getExpiresAt()).isEqualTo(tokenResponse.getAccessToken().getExpiresAt());
+		assertThat(withResponse.getAccessToken().getScopes()).isEqualTo(tokenResponse.getAccessToken().getScopes());
+		assertThat(withResponse.getRefreshToken().getTokenValue()).isEqualTo(tokenResponse.getRefreshToken().getTokenValue());
+		assertThat(withResponse.getAdditionalParameters()).isEqualTo(tokenResponse.getAdditionalParameters());
+	}
+
+	@Test
+	public void buildWhenResponseAndRefreshNullThenRefreshNull() {
+		Instant expiresAt = Instant.now().plusSeconds(5);
+		Set<String> scopes = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));
+		Map<String, Object> additionalParameters = new HashMap<>();
+		additionalParameters.put("param1", "value1");
+		additionalParameters.put("param2", "value2");
+
+		OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse
+				.withToken(TOKEN_VALUE)
+				.tokenType(OAuth2AccessToken.TokenType.BEARER)
+				.expiresIn(expiresAt.toEpochMilli())
+				.scopes(scopes)
+				.additionalParameters(additionalParameters)
+				.build();
+
+		OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse)
+				.build();
+
+		assertThat(withResponse.getRefreshToken()).isNull();
+	}
 }