Skip to content

Commit 3b42323

Browse files
committed
AuthorizationCodeRequestRedirectFilter -> always expand redirectUri
Fixes gh-4444
1 parent c204cc2 commit 3b42323

File tree

3 files changed

+39
-44
lines changed

3 files changed

+39
-44
lines changed

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProcessingFilter.java

+10-29
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,12 @@
3131
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3232
import org.springframework.security.web.util.matcher.RequestMatcher;
3333
import org.springframework.util.Assert;
34-
import org.springframework.util.CollectionUtils;
3534

3635
import javax.servlet.ServletException;
3736
import javax.servlet.http.HttpServletRequest;
3837
import javax.servlet.http.HttpServletResponse;
3938
import java.io.IOException;
4039

41-
import static org.springframework.security.oauth2.client.authentication.AuthorizationCodeRequestRedirectFilter.isDefaultRedirectUri;
42-
4340
/**
4441
* An implementation of an {@link AbstractAuthenticationProcessingFilter} that handles
4542
* the processing of an <i>OAuth 2.0 Authorization Response</i> for the authorization code grant flow.
@@ -136,12 +133,16 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ
136133
ClientRegistration clientRegistration = this.getClientRegistrationRepository().getRegistrationByClientId(
137134
matchingAuthorizationRequest.getClientId());
138135

139-
// If clientRegistration.redirectUri is the default one (with Uri template variables)
140-
// then use matchingAuthorizationRequest.redirectUri instead
141-
if (isDefaultRedirectUri(clientRegistration)) {
142-
clientRegistration = new ClientRegistrationBuilderWithUriOverrides(
143-
clientRegistration, matchingAuthorizationRequest.getRedirectUri()).build();
144-
}
136+
// The clientRegistration.redirectUri may contain Uri template variables, whether it's configured by
137+
// the user or configured by default. In these cases, the redirectUri will be expanded and ultimately changed
138+
// (by AuthorizationCodeRequestRedirectFilter) before setting it in the authorization request.
139+
// The resulting redirectUri used for the authorization request and saved within the AuthorizationRequestRepository
140+
// MUST BE the same one used to complete the authorization code flow.
141+
// Therefore, we'll create a copy of the clientRegistration and override the redirectUri
142+
// with the one contained in matchingAuthorizationRequest.
143+
clientRegistration = new ClientRegistration.Builder(clientRegistration)
144+
.redirectUri(matchingAuthorizationRequest.getRedirectUri())
145+
.build();
145146

146147
AuthorizationCodeAuthorizationResponseAttributes authorizationCodeResponseAttributes =
147148
this.authorizationCodeResponseConverter.apply(request);
@@ -203,24 +204,4 @@ private void assertMatchingAuthorizationRequest(HttpServletRequest request, Auth
203204
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
204205
}
205206
}
206-
207-
private static class ClientRegistrationBuilderWithUriOverrides extends ClientRegistration.Builder {
208-
209-
private ClientRegistrationBuilderWithUriOverrides(ClientRegistration clientRegistration, String redirectUri) {
210-
super(clientRegistration.getClientId());
211-
this.clientSecret(clientRegistration.getClientSecret());
212-
this.clientAuthenticationMethod(clientRegistration.getClientAuthenticationMethod());
213-
this.authorizedGrantType(clientRegistration.getAuthorizedGrantType());
214-
this.redirectUri(redirectUri);
215-
if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) {
216-
this.scopes(clientRegistration.getScopes().stream().toArray(String[]::new));
217-
}
218-
this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri());
219-
this.tokenUri(clientRegistration.getProviderDetails().getTokenUri());
220-
this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoUri());
221-
this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri());
222-
this.clientName(clientRegistration.getClientName());
223-
this.clientAlias(clientRegistration.getClientAlias());
224-
}
225-
}
226207
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeRequestRedirectFilter.java

+12-15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import javax.servlet.http.HttpServletResponse;
3333
import java.io.IOException;
3434
import java.net.URI;
35+
import java.util.HashMap;
36+
import java.util.Map;
3537

3638
import static org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProcessingFilter.AUTHORIZE_BASE_URI;
3739

@@ -61,7 +63,6 @@ public class AuthorizationCodeRequestRedirectFilter extends OncePerRequestFilter
6163
public static final String AUTHORIZATION_BASE_URI = "/oauth2/authorization/code";
6264
private static final String CLIENT_ALIAS_VARIABLE_NAME = "clientAlias";
6365
private static final String AUTHORIZATION_URI = AUTHORIZATION_BASE_URI + "/{" + CLIENT_ALIAS_VARIABLE_NAME + "}";
64-
private static final String DEFAULT_REDIRECT_URI_TEMPLATE = "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}";
6566
private final AntPathRequestMatcher authorizationRequestMatcher;
6667
private final ClientRegistrationRepository clientRegistrationRepository;
6768
private final AuthorizationRequestUriBuilder authorizationUriBuilder;
@@ -114,12 +115,7 @@ protected void sendRedirectForAuthorizationCode(HttpServletRequest request, Http
114115
throw new IllegalArgumentException("Invalid Client Identifier (Alias): " + clientAlias);
115116
}
116117

117-
String redirectUriStr;
118-
if (isDefaultRedirectUri(clientRegistration)) {
119-
redirectUriStr = this.expandDefaultRedirectUri(request, clientRegistration);
120-
} else {
121-
redirectUriStr = clientRegistration.getRedirectUri();
122-
}
118+
String redirectUriStr = this.expandRedirectUri(request, clientRegistration);
123119

124120
AuthorizationRequestAttributes authorizationRequestAttributes =
125121
AuthorizationRequestAttributes.withAuthorizationCode()
@@ -145,15 +141,16 @@ protected void unsuccessfulRedirectForAuthorizationCode(HttpServletRequest reque
145141
response.sendError(HttpServletResponse.SC_BAD_REQUEST, failed.getMessage());
146142
}
147143

148-
static boolean isDefaultRedirectUri(ClientRegistration clientRegistration) {
149-
return DEFAULT_REDIRECT_URI_TEMPLATE.equals(clientRegistration.getRedirectUri());
150-
}
144+
private String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration) {
145+
Map<String, String> uriVariables = new HashMap<>();
146+
uriVariables.put("scheme", request.getScheme());
147+
uriVariables.put("serverName", request.getServerName());
148+
uriVariables.put("serverPort", String.valueOf(request.getServerPort()));
149+
uriVariables.put("baseAuthorizeUri", AUTHORIZE_BASE_URI);
150+
uriVariables.put("clientAlias", clientRegistration.getClientAlias());
151151

152-
private String expandDefaultRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration) {
153-
return UriComponentsBuilder.fromUriString(DEFAULT_REDIRECT_URI_TEMPLATE)
154-
.buildAndExpand(request.getScheme(), request.getServerName(), request.getServerPort(),
155-
AUTHORIZE_BASE_URI, clientRegistration.getClientAlias())
156-
.encode()
152+
return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri())
153+
.buildAndExpand(uriVariables)
157154
.toUriString();
158155
}
159156
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java

+17
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,23 @@ public Builder(ClientRegistrationProperties clientRegistrationProperties) {
195195
this.clientAlias(clientRegistrationProperties.getClientAlias());
196196
}
197197

198+
public Builder(ClientRegistration clientRegistration) {
199+
this(clientRegistration.getClientId());
200+
this.clientSecret(clientRegistration.getClientSecret());
201+
this.clientAuthenticationMethod(clientRegistration.getClientAuthenticationMethod());
202+
this.authorizedGrantType(clientRegistration.getAuthorizedGrantType());
203+
this.redirectUri(clientRegistration.getRedirectUri());
204+
if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) {
205+
this.scopes(clientRegistration.getScopes().stream().toArray(String[]::new));
206+
}
207+
this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri());
208+
this.tokenUri(clientRegistration.getProviderDetails().getTokenUri());
209+
this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoUri());
210+
this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri());
211+
this.clientName(clientRegistration.getClientName());
212+
this.clientAlias(clientRegistration.getClientAlias());
213+
}
214+
198215
public Builder clientSecret(String clientSecret) {
199216
this.clientSecret = clientSecret;
200217
return this;

0 commit comments

Comments
 (0)