Merge branch '1.4.x'

This commit is contained in:
Joe Grandja
2025-02-14 12:09:28 -05:00
2 changed files with 22 additions and 19 deletions

View File

@@ -138,6 +138,25 @@ public final class OAuth2DeviceCodeAuthenticationProvider implements Authenticat
// In https://www.rfc-editor.org/rfc/rfc8628.html#section-3.5,
// the following error codes are defined:
// expired_token
// The "device_code" has expired, and the device authorization
// session has concluded. The client MAY commence a new device
// authorization request but SHOULD wait for user interaction before
// restarting to avoid unnecessary polling.
if (deviceCode.isExpired()) {
if (!deviceCode.isInvalidated()) {
// Invalidate the device code
authorization = OAuth2Authorization.from(authorization).invalidate(deviceCode.getToken()).build();
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);
}
// authorization_pending
// The authorization request is still pending as the end user hasn't
// yet completed the user-interaction steps (Section 3.3). The
@@ -166,23 +185,6 @@ public final class OAuth2DeviceCodeAuthenticationProvider implements Authenticat
throw new OAuth2AuthenticationException(error);
}
// expired_token
// The "device_code" has expired, and the device authorization
// session has concluded. The client MAY commence a new device
// authorization request but SHOULD wait for user interaction before
// restarting to avoid unnecessary polling.
if (deviceCode.isExpired()) {
// Invalidate the device code
authorization = OAuth2Authorization.from(authorization).invalidate(deviceCode.getToken()).build();
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);
}
// Verify the DPoP Proof (if available)
Jwt dPoPProof = DPoPProofVerifier.verifyIfAvailable(deviceCodeAuthentication);

View File

@@ -209,6 +209,7 @@ public class OAuth2DeviceCodeAuthenticationProviderTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
Authentication authentication = createAuthentication(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createDeviceCode())
.token(createUserCode())
.build();
given(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).willReturn(authorization);
@@ -227,7 +228,7 @@ public class OAuth2DeviceCodeAuthenticationProviderTests {
}
@Test
public void authenticateWhenDeviceCodeIsInvalidatedThenThrowOAuth2AuthenticationException() {
public void authenticateWhenDeviceCodeAndUserCodeAreInvalidatedThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
Authentication authentication = createAuthentication(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
@@ -255,7 +256,7 @@ public class OAuth2DeviceCodeAuthenticationProviderTests {
Authentication authentication = createAuthentication(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.token(createExpiredDeviceCode())
.token(createUserCode(), withInvalidated())
.token(createUserCode())
.build();
given(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).willReturn(authorization);
// @formatter:off