Provide configurable Clock in OAuth2AuthorizedClientProvider impls
Fixes gh-7114
This commit is contained in:
parent
052256db0a
commit
bc38a4a3cc
|
@ -25,6 +25,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA
|
||||||
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient =
|
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient =
|
||||||
new DefaultClientCredentialsTokenResponseClient();
|
new DefaultClientCredentialsTokenResponseClient();
|
||||||
private Duration clockSkew = Duration.ofSeconds(60);
|
private Duration clockSkew = Duration.ofSeconds(60);
|
||||||
|
private Clock clock = Clock.systemUTC();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
* Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
||||||
|
@ -84,7 +86,7 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
||||||
return token.getExpiresAt().isBefore(Instant.now().minus(this.clockSkew));
|
return token.getExpiresAt().isBefore(Instant.now(this.clock).minus(this.clockSkew));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +102,7 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the
|
* Sets the maximum acceptable clock skew, which is used when checking the
|
||||||
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
*/
|
*/
|
||||||
|
@ -109,4 +111,14 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA
|
||||||
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
||||||
this.clockSkew = clockSkew;
|
this.clockSkew = clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
*/
|
||||||
|
public void setClock(Clock clock) {
|
||||||
|
Assert.notNull(clock, "clock cannot be null");
|
||||||
|
this.clock = clock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple
|
||||||
private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient =
|
private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient =
|
||||||
new WebClientReactiveClientCredentialsTokenResponseClient();
|
new WebClientReactiveClientCredentialsTokenResponseClient();
|
||||||
private Duration clockSkew = Duration.ofSeconds(60);
|
private Duration clockSkew = Duration.ofSeconds(60);
|
||||||
|
private Clock clock = Clock.systemUTC();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
* Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
||||||
|
@ -80,7 +82,7 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
||||||
return token.getExpiresAt().isBefore(Instant.now().minus(this.clockSkew));
|
return token.getExpiresAt().isBefore(Instant.now(this.clock).minus(this.clockSkew));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +98,7 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the
|
* Sets the maximum acceptable clock skew, which is used when checking the
|
||||||
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
*/
|
*/
|
||||||
|
@ -105,4 +107,14 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple
|
||||||
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
||||||
this.clockSkew = clockSkew;
|
this.clockSkew = clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
*/
|
||||||
|
public void setClock(Clock clock) {
|
||||||
|
Assert.notNull(clock, "clock cannot be null");
|
||||||
|
this.clock = clock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentia
|
||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
|
import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -128,6 +130,7 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
public class RefreshTokenGrantBuilder implements Builder {
|
public class RefreshTokenGrantBuilder implements Builder {
|
||||||
private OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient;
|
private OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient;
|
||||||
private Duration clockSkew;
|
private Duration clockSkew;
|
||||||
|
private Clock clock;
|
||||||
|
|
||||||
private RefreshTokenGrantBuilder() {
|
private RefreshTokenGrantBuilder() {
|
||||||
}
|
}
|
||||||
|
@ -145,7 +148,7 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
* @return the {@link RefreshTokenGrantBuilder}
|
* @return the {@link RefreshTokenGrantBuilder}
|
||||||
|
@ -155,6 +158,17 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
* @return the {@link RefreshTokenGrantBuilder}
|
||||||
|
*/
|
||||||
|
public RefreshTokenGrantBuilder clock(Clock clock) {
|
||||||
|
this.clock = clock;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an instance of {@link RefreshTokenOAuth2AuthorizedClientProvider}.
|
* Builds an instance of {@link RefreshTokenOAuth2AuthorizedClientProvider}.
|
||||||
*
|
*
|
||||||
|
@ -169,6 +183,9 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
if (this.clockSkew != null) {
|
if (this.clockSkew != null) {
|
||||||
authorizedClientProvider.setClockSkew(this.clockSkew);
|
authorizedClientProvider.setClockSkew(this.clockSkew);
|
||||||
}
|
}
|
||||||
|
if (this.clock != null) {
|
||||||
|
authorizedClientProvider.setClock(this.clock);
|
||||||
|
}
|
||||||
return authorizedClientProvider;
|
return authorizedClientProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,6 +219,7 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
public class ClientCredentialsGrantBuilder implements Builder {
|
public class ClientCredentialsGrantBuilder implements Builder {
|
||||||
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient;
|
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient;
|
||||||
private Duration clockSkew;
|
private Duration clockSkew;
|
||||||
|
private Clock clock;
|
||||||
|
|
||||||
private ClientCredentialsGrantBuilder() {
|
private ClientCredentialsGrantBuilder() {
|
||||||
}
|
}
|
||||||
|
@ -219,7 +237,7 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
* @return the {@link ClientCredentialsGrantBuilder}
|
* @return the {@link ClientCredentialsGrantBuilder}
|
||||||
|
@ -229,6 +247,17 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
* @return the {@link ClientCredentialsGrantBuilder}
|
||||||
|
*/
|
||||||
|
public ClientCredentialsGrantBuilder clock(Clock clock) {
|
||||||
|
this.clock = clock;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider}.
|
* Builds an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider}.
|
||||||
*
|
*
|
||||||
|
@ -243,6 +272,9 @@ public final class OAuth2AuthorizedClientProviderBuilder {
|
||||||
if (this.clockSkew != null) {
|
if (this.clockSkew != null) {
|
||||||
authorizedClientProvider.setClockSkew(this.clockSkew);
|
authorizedClientProvider.setClockSkew(this.clockSkew);
|
||||||
}
|
}
|
||||||
|
if (this.clock != null) {
|
||||||
|
authorizedClientProvider.setClock(this.clock);
|
||||||
|
}
|
||||||
return authorizedClientProvider;
|
return authorizedClientProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@ import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGra
|
||||||
import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient;
|
import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -128,6 +130,7 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
public class RefreshTokenGrantBuilder implements Builder {
|
public class RefreshTokenGrantBuilder implements Builder {
|
||||||
private ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient;
|
private ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient;
|
||||||
private Duration clockSkew;
|
private Duration clockSkew;
|
||||||
|
private Clock clock;
|
||||||
|
|
||||||
private RefreshTokenGrantBuilder() {
|
private RefreshTokenGrantBuilder() {
|
||||||
}
|
}
|
||||||
|
@ -145,7 +148,7 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
* @return the {@link RefreshTokenGrantBuilder}
|
* @return the {@link RefreshTokenGrantBuilder}
|
||||||
|
@ -155,6 +158,17 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
* @return the {@link RefreshTokenGrantBuilder}
|
||||||
|
*/
|
||||||
|
public RefreshTokenGrantBuilder clock(Clock clock) {
|
||||||
|
this.clock = clock;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an instance of {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}.
|
* Builds an instance of {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}.
|
||||||
*
|
*
|
||||||
|
@ -169,6 +183,9 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
if (this.clockSkew != null) {
|
if (this.clockSkew != null) {
|
||||||
authorizedClientProvider.setClockSkew(this.clockSkew);
|
authorizedClientProvider.setClockSkew(this.clockSkew);
|
||||||
}
|
}
|
||||||
|
if (this.clock != null) {
|
||||||
|
authorizedClientProvider.setClock(this.clock);
|
||||||
|
}
|
||||||
return authorizedClientProvider;
|
return authorizedClientProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,6 +219,7 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
public class ClientCredentialsGrantBuilder implements Builder {
|
public class ClientCredentialsGrantBuilder implements Builder {
|
||||||
private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient;
|
private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> accessTokenResponseClient;
|
||||||
private Duration clockSkew;
|
private Duration clockSkew;
|
||||||
|
private Clock clock;
|
||||||
|
|
||||||
private ClientCredentialsGrantBuilder() {
|
private ClientCredentialsGrantBuilder() {
|
||||||
}
|
}
|
||||||
|
@ -219,7 +237,7 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
* Sets the maximum acceptable clock skew, which is used when checking the access token expiry.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
* @return the {@link ClientCredentialsGrantBuilder}
|
* @return the {@link ClientCredentialsGrantBuilder}
|
||||||
|
@ -229,6 +247,17 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
* @return the {@link ClientCredentialsGrantBuilder}
|
||||||
|
*/
|
||||||
|
public ClientCredentialsGrantBuilder clock(Clock clock) {
|
||||||
|
this.clock = clock;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an instance of {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider}.
|
* Builds an instance of {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider}.
|
||||||
*
|
*
|
||||||
|
@ -243,6 +272,9 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder {
|
||||||
if (this.clockSkew != null) {
|
if (this.clockSkew != null) {
|
||||||
authorizedClientProvider.setClockSkew(this.clockSkew);
|
authorizedClientProvider.setClockSkew(this.clockSkew);
|
||||||
}
|
}
|
||||||
|
if (this.clock != null) {
|
||||||
|
authorizedClientProvider.setClock(this.clock);
|
||||||
|
}
|
||||||
return authorizedClientProvider;
|
return authorizedClientProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -44,6 +45,7 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A
|
||||||
private OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient =
|
private OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient =
|
||||||
new DefaultRefreshTokenTokenResponseClient();
|
new DefaultRefreshTokenTokenResponseClient();
|
||||||
private Duration clockSkew = Duration.ofSeconds(60);
|
private Duration clockSkew = Duration.ofSeconds(60);
|
||||||
|
private Clock clock = Clock.systemUTC();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
* Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
||||||
|
@ -92,7 +94,7 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
||||||
return token.getExpiresAt().isBefore(Instant.now().minus(this.clockSkew));
|
return token.getExpiresAt().isBefore(Instant.now(this.clock).minus(this.clockSkew));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +110,7 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the
|
* Sets the maximum acceptable clock skew, which is used when checking the
|
||||||
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
*/
|
*/
|
||||||
|
@ -117,4 +119,14 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A
|
||||||
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
||||||
this.clockSkew = clockSkew;
|
this.clockSkew = clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
*/
|
||||||
|
public void setClock(Clock clock) {
|
||||||
|
Assert.notNull(clock, "clock cannot be null");
|
||||||
|
this.clock = clock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -44,6 +45,7 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements
|
||||||
private ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient =
|
private ReactiveOAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> accessTokenResponseClient =
|
||||||
new WebClientReactiveRefreshTokenTokenResponseClient();
|
new WebClientReactiveRefreshTokenTokenResponseClient();
|
||||||
private Duration clockSkew = Duration.ofSeconds(60);
|
private Duration clockSkew = Duration.ofSeconds(60);
|
||||||
|
private Clock clock = Clock.systemUTC();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
* Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}.
|
||||||
|
@ -91,7 +93,7 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
private boolean hasTokenExpired(AbstractOAuth2Token token) {
|
||||||
return token.getExpiresAt().isBefore(Instant.now().minus(this.clockSkew));
|
return token.getExpiresAt().isBefore(Instant.now(this.clock).minus(this.clockSkew));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +109,7 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements
|
||||||
/**
|
/**
|
||||||
* Sets the maximum acceptable clock skew, which is used when checking the
|
* Sets the maximum acceptable clock skew, which is used when checking the
|
||||||
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
* {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds.
|
||||||
* An access token is considered expired if it's before {@code Instant.now() - clockSkew}.
|
* An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}.
|
||||||
*
|
*
|
||||||
* @param clockSkew the maximum acceptable clock skew
|
* @param clockSkew the maximum acceptable clock skew
|
||||||
*/
|
*/
|
||||||
|
@ -116,4 +118,14 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements
|
||||||
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
Assert.isTrue(clockSkew.getSeconds() >= 0, "clockSkew must be >= 0");
|
||||||
this.clockSkew = clockSkew;
|
this.clockSkew = clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry.
|
||||||
|
*
|
||||||
|
* @param clock the clock
|
||||||
|
*/
|
||||||
|
public void setClock(Clock clock) {
|
||||||
|
Assert.notNull(clock, "clock cannot be null");
|
||||||
|
this.clock = clock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,13 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests {
|
||||||
.hasMessage("clockSkew must be >= 0");
|
.hasMessage("clockSkew must be >= 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setClockWhenNullThenThrowIllegalArgumentException() {
|
||||||
|
assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("clock cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null))
|
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null))
|
||||||
|
|
|
@ -79,6 +79,13 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests {
|
||||||
.hasMessage("clockSkew must be >= 0");
|
.hasMessage("clockSkew must be >= 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setClockWhenNullThenThrowIllegalArgumentException() {
|
||||||
|
assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("clock cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block())
|
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block())
|
||||||
|
|
|
@ -87,6 +87,13 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests {
|
||||||
.hasMessage("clockSkew must be >= 0");
|
.hasMessage("clockSkew must be >= 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setClockWhenNullThenThrowIllegalArgumentException() {
|
||||||
|
assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("clock cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null))
|
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null))
|
||||||
|
|
|
@ -89,6 +89,13 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests {
|
||||||
.hasMessage("clockSkew must be >= 0");
|
.hasMessage("clockSkew must be >= 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setClockWhenNullThenThrowIllegalArgumentException() {
|
||||||
|
assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null))
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("clock cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block())
|
assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block())
|
||||||
|
|
Loading…
Reference in New Issue