diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java index 83602d754..6535136fa 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java @@ -36,6 +36,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.oauth2.core.AbstractOAuth2Token; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.ClaimAccessor; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; @@ -154,12 +155,12 @@ public Authentication authenticate(Authentication authentication) throws Authent if (!authorizationCode.isActive()) { if (authorizationCode.isInvalidated()) { - OAuth2Token token = authorization.getRefreshToken() != null ? - authorization.getRefreshToken().getToken() : - authorization.getAccessToken().getToken(); + OAuth2Authorization.Token token = authorization.getRefreshToken() != null ? + authorization.getRefreshToken() : + authorization.getAccessToken(); if (token != null) { // Invalidate the access (and refresh) token as the client is attempting to use the authorization code more than once - authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, token); + authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, token.getToken()); this.authorizationService.save(authorization); if (this.logger.isWarnEnabled()) { this.logger.warn(LogMessage.format("Invalidated authorization token(s) previously issued to registered client '%s'", registeredClient.getId())); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java index 2378a559e..f50757721 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java @@ -283,6 +283,33 @@ public void authenticateWhenInvalidatedCodeThenThrowOAuth2AuthenticationExceptio assertThat(updatedAuthorization.getRefreshToken().isInvalidated()).isTrue(); } + // gh PR 1233 + @Test + public void authenticateWhenInvalidatedCodeAndNullRefreshAndAccessTokensThenThrowOAuth2AuthenticationException() { + RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); + OAuth2AuthorizationCode authorizationCode = new OAuth2AuthorizationCode( + AUTHORIZATION_CODE, Instant.now(), Instant.now().plusSeconds(120)); + OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient, authorizationCode) + .token(authorizationCode, (metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)) + .build(); + + when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) + .thenReturn(authorization); + + OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( + registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); + OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute( + OAuth2AuthorizationRequest.class.getName()); + OAuth2AuthorizationCodeAuthenticationToken authentication = + new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null); + + assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .extracting("errorCode") + .isEqualTo(OAuth2ErrorCodes.INVALID_GRANT); + } + // gh-290 @Test public void authenticateWhenExpiredCodeThenThrowOAuth2AuthenticationException() {