diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProvider.java index 9b551742..0d444d7a 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProvider.java @@ -134,10 +134,6 @@ public final class OAuth2DeviceCodeAuthenticationProvider implements Authenticat throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } - if (deviceCode.isInvalidated() && !userCode.isInvalidated()) { - throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); - } - // In https://www.rfc-editor.org/rfc/rfc8628.html#section-3.5, // the following error codes are defined: @@ -147,12 +143,14 @@ public final class OAuth2DeviceCodeAuthenticationProvider implements Authenticat // authorization request but SHOULD wait for user interaction before // restarting to avoid unnecessary polling. if (deviceCode.isExpired()) { - // Invalidate the device code - authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, deviceCode.getToken()); - this.authorizationService.save(authorization); - if (this.logger.isWarnEnabled()) { - this.logger.warn(LogMessage.format("Invalidated device code used by registered client '%s'", - authorization.getRegisteredClientId())); + if (!deviceCode.isInvalidated()) { + // Invalidate the device code + authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, deviceCode.getToken()); + this.authorizationService.save(authorization); + if (this.logger.isWarnEnabled()) { + this.logger.warn(LogMessage.format("Invalidated device code used by registered client '%s'", + authorization.getRegisteredClientId())); + } } OAuth2Error error = new OAuth2Error(EXPIRED_TOKEN, null, DEVICE_ERROR_URI); throw new OAuth2AuthenticationException(error); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProviderTests.java index 0a457ad8..5113f7c3 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -232,29 +232,6 @@ public class OAuth2DeviceCodeAuthenticationProviderTests { verifyNoInteractions(this.tokenGenerator); } - @Test - public void authenticateWhenDeviceCodeIsInvalidatedThenThrowOAuth2AuthenticationException() { - RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); - Authentication authentication = createAuthentication(registeredClient); - OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createDeviceCode(), withInvalidated()) - .token(createUserCode()) - .build(); - given(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).willReturn(authorization); - // @formatter:off - assertThatExceptionOfType(OAuth2AuthenticationException.class) - .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .extracting(OAuth2AuthenticationException::getError) - .extracting(OAuth2Error::getErrorCode) - .isEqualTo(OAuth2ErrorCodes.INVALID_GRANT); - // @formatter:on - - verify(this.authorizationService).findByToken(DEVICE_CODE, - OAuth2DeviceCodeAuthenticationProvider.DEVICE_CODE_TOKEN_TYPE); - verifyNoMoreInteractions(this.authorizationService); - verifyNoInteractions(this.tokenGenerator); - } - @Test public void authenticateWhenDeviceCodeIsExpiredThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();