From 5458e0855a547e9125a1ca1466621eb0140ac2d5 Mon Sep 17 00:00:00 2001 From: Joe Grandja <10884212+jgrandja@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:07:58 -0400 Subject: [PATCH] request_uri used in PAR must be bound to the client Issue gh-1925 Closes gh-1971 --- ...tionCodeRequestAuthenticationProvider.java | 8 +++-- ...odeRequestAuthenticationProviderTests.java | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java index 87e96b80..62b1d16e 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java @@ -356,9 +356,13 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen OAuth2AuthorizationRequest authorizationRequest = authorization .getAttribute(OAuth2AuthorizationRequest.class.getName()); + if (!authorizationCodeRequestAuthentication.getClientId().equals(authorizationRequest.getClientId())) { + throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.CLIENT_ID, + authorizationCodeRequestAuthentication, null); + } + return new OAuth2AuthorizationCodeRequestAuthenticationToken( - authorizationCodeRequestAuthentication.getAuthorizationUri(), - authorizationCodeRequestAuthentication.getClientId(), + authorizationCodeRequestAuthentication.getAuthorizationUri(), authorizationRequest.getClientId(), (Authentication) authorizationCodeRequestAuthentication.getPrincipal(), authorizationRequest.getRedirectUri(), authorizationRequest.getState(), authorizationRequest.getScopes(), authorizationRequest.getAdditionalParameters()); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java index ef7dcbb8..def23a36 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java @@ -660,6 +660,36 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests { OAuth2ErrorCodes.INVALID_REQUEST, "request_uri", null)); } + @Test + public void authenticateWhenAuthorizationCodeRequestWithRequestUriIssuedToAnotherClientThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() { + RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); + given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) + .willReturn(registeredClient); + + RegisteredClient anotherRegisteredClient = TestRegisteredClients.registeredClient2().build(); + given(this.registeredClientRepository.findByClientId(eq(anotherRegisteredClient.getClientId()))) + .willReturn(anotherRegisteredClient); + + OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri + .create(); + Map additionalParameters = new HashMap<>(); + additionalParameters.put("request_uri", pushedAuthorizationRequestUri.getRequestUri()); + OAuth2Authorization authorization = TestOAuth2Authorizations + .authorization(registeredClient, additionalParameters) + .build(); + given(this.authorizationService.findByToken(eq(pushedAuthorizationRequestUri.getState()), eq(STATE_TOKEN_TYPE))) + .willReturn(authorization); + + OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( + AUTHORIZATION_URI, anotherRegisteredClient.getClientId(), this.principal, null, null, null, + additionalParameters); + + assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) + .isInstanceOf(OAuth2AuthorizationCodeRequestAuthenticationException.class) + .satisfies((ex) -> assertAuthenticationException((OAuth2AuthorizationCodeRequestAuthenticationException) ex, + OAuth2ErrorCodes.INVALID_REQUEST, "client_id", null)); + } + @Test public void authenticateWhenAuthorizationCodeNotGeneratedThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();