소스 검색

Add configuration for authorization code time-to-live

Closes gh-642
Gyeongwon, Do 3 년 전
부모
커밋
303043ea78

+ 3 - 2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java

@@ -17,7 +17,6 @@ package org.springframework.security.oauth2.server.authorization.authentication;
 
 import java.security.Principal;
 import java.time.Instant;
-import java.time.temporal.ChronoUnit;
 import java.util.Base64;
 import java.util.Collections;
 import java.util.HashMap;
@@ -565,8 +564,10 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
 					!OAuth2ParameterNames.CODE.equals(context.getTokenType().getValue())) {
 				return null;
 			}
+			RegisteredClient registeredClient = context.getRegisteredClient();
+
 			Instant issuedAt = Instant.now();
-			Instant expiresAt = issuedAt.plus(5, ChronoUnit.MINUTES);		// TODO Allow configuration for authorization code time-to-live
+			Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAuthorizationCodeTimeToLive());
 			return new OAuth2AuthorizationCode(this.authorizationCodeGenerator.generateKey(), issuedAt, expiresAt);
 		}
 

+ 5 - 0
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/ConfigurationSettingNames.java

@@ -128,6 +128,11 @@ public final class ConfigurationSettingNames {
 	public static final class Token {
 		private static final String TOKEN_SETTINGS_NAMESPACE = SETTINGS_NAMESPACE.concat("token.");
 
+		/**
+		 * Set the time-to-live for an authorization code.
+		 */
+		public static final String AUTHORIZATION_CODE_TIME_TO_LIVE = TOKEN_SETTINGS_NAMESPACE.concat("authorization-code-time-to-live");
+
 		/**
 		 * Set the time-to-live for an access token.
 		 */

+ 23 - 0
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/TokenSettings.java

@@ -37,6 +37,15 @@ public final class TokenSettings extends AbstractSettings {
 		super(settings);
 	}
 
+	/**
+	 * Returns the time-to-live for an authorization code. The default is 5 minutes.
+	 *
+	 * @return the time-to-live for an authorization code
+	 */
+	public Duration getAuthorizationCodeTimeToLive() {
+		return getSetting(ConfigurationSettingNames.Token.AUTHORIZATION_CODE_TIME_TO_LIVE);
+	}
+
 	/**
 	 * Returns the time-to-live for an access token. The default is 5 minutes.
 	 *
@@ -91,6 +100,7 @@ public final class TokenSettings extends AbstractSettings {
 	 */
 	public static Builder builder() {
 		return new Builder()
+				.authorizationCodeTimeToLive(Duration.ofMinutes(5))
 				.accessTokenTimeToLive(Duration.ofMinutes(5))
 				.accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)
 				.reuseRefreshTokens(true)
@@ -118,6 +128,19 @@ public final class TokenSettings extends AbstractSettings {
 		private Builder() {
 		}
 
+		/**
+		 * Set the time-to-live for an access token. Must be greater than {@code Duration.ZERO}.
+		 * A maximum  authorization code lifetime of 10 minutes is RECOMMENDED
+		 *
+		 * @param authorizationCodeTimeToLive the time-to-live for an authorization code
+		 * @return the {@link Builder} for further configuration
+		 */
+		public Builder authorizationCodeTimeToLive(Duration authorizationCodeTimeToLive) {
+			Assert.notNull(authorizationCodeTimeToLive, "authorizationCodeTimeToLive cannot be null");
+			Assert.isTrue(authorizationCodeTimeToLive.getSeconds() > 0, "authorizationCodeTimeToLive must be greater than Duration.ZERO");
+			return setting(ConfigurationSettingNames.Token.AUTHORIZATION_CODE_TIME_TO_LIVE, authorizationCodeTimeToLive);
+		}
+
 		/**
 		 * Set the time-to-live for an access token. Must be greater than {@code Duration.ZERO}.
 		 *

+ 30 - 2
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/TokenSettingsTests.java

@@ -35,7 +35,8 @@ public class TokenSettingsTests {
 	@Test
 	public void buildWhenDefaultThenDefaultsAreSet() {
 		TokenSettings tokenSettings = TokenSettings.builder().build();
-		assertThat(tokenSettings.getSettings()).hasSize(5);
+		assertThat(tokenSettings.getSettings()).hasSize(6);
+		assertThat(tokenSettings.getAuthorizationCodeTimeToLive()).isEqualTo(Duration.ofMinutes(5));
 		assertThat(tokenSettings.getAccessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5));
 		assertThat(tokenSettings.getAccessTokenFormat()).isEqualTo(OAuth2TokenFormat.SELF_CONTAINED);
 		assertThat(tokenSettings.isReuseRefreshTokens()).isTrue();
@@ -43,6 +44,33 @@ public class TokenSettingsTests {
 		assertThat(tokenSettings.getIdTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
 	}
 
+	@Test
+	public void authorizationCodeTimeToLiveWhenProvidedThenSet() {
+		Duration authorizationCodeTimeToLive = Duration.ofMinutes(10);
+		TokenSettings tokenSettings = TokenSettings.builder()
+				.authorizationCodeTimeToLive(authorizationCodeTimeToLive)
+				.build();
+		assertThat(tokenSettings.getAuthorizationCodeTimeToLive()).isEqualTo(authorizationCodeTimeToLive);
+	}
+
+	@Test
+	public void authorizationCodeTimeToLiveWhenNullOrZeroOrNegativeThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() -> TokenSettings.builder().authorizationCodeTimeToLive(null))
+				.isInstanceOf(IllegalArgumentException.class)
+				.extracting(Throwable::getMessage)
+				.isEqualTo("authorizationCodeTimeToLive cannot be null");
+
+		assertThatThrownBy(() -> TokenSettings.builder().authorizationCodeTimeToLive(Duration.ZERO))
+				.isInstanceOf(IllegalArgumentException.class)
+				.extracting(Throwable::getMessage)
+				.isEqualTo("authorizationCodeTimeToLive must be greater than Duration.ZERO");
+
+		assertThatThrownBy(() -> TokenSettings.builder().authorizationCodeTimeToLive(Duration.ofSeconds(-10)))
+				.isInstanceOf(IllegalArgumentException.class)
+				.extracting(Throwable::getMessage)
+				.isEqualTo("authorizationCodeTimeToLive must be greater than Duration.ZERO");
+	}
+
 	@Test
 	public void accessTokenTimeToLiveWhenProvidedThenSet() {
 		Duration accessTokenTimeToLive = Duration.ofMinutes(10);
@@ -136,7 +164,7 @@ public class TokenSettingsTests {
 				.setting("name1", "value1")
 				.settings(settings -> settings.put("name2", "value2"))
 				.build();
-		assertThat(tokenSettings.getSettings()).hasSize(7);
+		assertThat(tokenSettings.getSettings()).hasSize(8);
 		assertThat(tokenSettings.<String>getSetting("name1")).isEqualTo("value1");
 		assertThat(tokenSettings.<String>getSetting("name2")).isEqualTo("value2");
 	}