Skip to content

Commit e6bc73f

Browse files
author
Steve Riesenberg
committed
Fix token expired and not before use check
Closes gh-290
1 parent 5e0fe9c commit e6bc73f

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@
4141
import org.springframework.security.oauth2.jwt.Jwt;
4242
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
4343
import org.springframework.security.oauth2.jwt.JwtEncoder;
44+
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
4445
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
46+
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
4547
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
48+
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
4649
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
4750
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
48-
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
49-
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
50-
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
5151
import org.springframework.util.Assert;
5252
import org.springframework.util.StringUtils;
5353

@@ -135,7 +135,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
135135
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
136136
}
137137

138-
if (authorizationCode.isInvalidated()) {
138+
if (!authorizationCode.isActive()) {
139139
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
140140
}
141141

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java

+60-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.time.Duration;
2020
import java.time.Instant;
2121
import java.time.temporal.ChronoUnit;
22+
import java.util.Collections;
2223
import java.util.HashMap;
2324
import java.util.HashSet;
2425
import java.util.Map;
@@ -45,14 +46,14 @@
4546
import org.springframework.security.oauth2.jwt.Jwt;
4647
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
4748
import org.springframework.security.oauth2.jwt.JwtEncoder;
49+
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
4850
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
51+
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
4952
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
53+
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
5054
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
5155
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
5256
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
53-
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
54-
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
55-
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
5657

5758
import static org.assertj.core.api.Assertions.assertThat;
5859
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -222,6 +223,62 @@ public void authenticateWhenInvalidatedCodeThenThrowOAuth2AuthenticationExceptio
222223
.isEqualTo(OAuth2ErrorCodes.INVALID_GRANT);
223224
}
224225

226+
// gh-290
227+
@Test
228+
public void authenticateWhenExpiredCodeThenThrowOAuth2AuthenticationException() throws InterruptedException {
229+
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
230+
Instant now = Instant.now();
231+
OAuth2AuthorizationCode authorizationCode = new OAuth2AuthorizationCode(
232+
AUTHORIZATION_CODE, now, now.plusNanos(1));
233+
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
234+
.token(authorizationCode)
235+
.build();
236+
when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
237+
.thenReturn(authorization);
238+
239+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
240+
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
241+
OAuth2AuthorizationRequest.class.getName());
242+
OAuth2AuthorizationCodeAuthenticationToken authentication =
243+
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
244+
245+
// Busy wait a brief moment for token to expire. TODO: Add a way to mock the underlying java.time.Clock?
246+
while (!Instant.now().isAfter(authorizationCode.getExpiresAt())) {
247+
Thread.sleep(0, 1);
248+
}
249+
250+
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
251+
.isInstanceOf(OAuth2AuthenticationException.class)
252+
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
253+
.extracting("errorCode")
254+
.isEqualTo(OAuth2ErrorCodes.INVALID_GRANT);
255+
}
256+
257+
// gh-290
258+
@Test
259+
public void authenticateWhenCodeIsBeforeUseThenThrowOAuth2AuthenticationException() throws InterruptedException {
260+
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
261+
OAuth2AuthorizationCode authorizationCode = new OAuth2AuthorizationCode(
262+
AUTHORIZATION_CODE, Instant.now(), Instant.now().plusSeconds(240));
263+
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
264+
.token(authorizationCode, (metadata) -> metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, Collections.singletonMap("nbf", Instant.now().plusSeconds(120))))
265+
.build();
266+
when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
267+
.thenReturn(authorization);
268+
269+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
270+
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
271+
OAuth2AuthorizationRequest.class.getName());
272+
OAuth2AuthorizationCodeAuthenticationToken authentication =
273+
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
274+
275+
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
276+
.isInstanceOf(OAuth2AuthenticationException.class)
277+
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
278+
.extracting("errorCode")
279+
.isEqualTo(OAuth2ErrorCodes.INVALID_GRANT);
280+
}
281+
225282
@Test
226283
public void authenticateWhenValidCodeThenReturnAccessToken() {
227284
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();

0 commit comments

Comments
 (0)