diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProcessingFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProcessingFilter.java index b045649f3c..3554725a57 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProcessingFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProcessingFilter.java @@ -31,15 +31,12 @@ import org.springframework.security.web.authentication.AbstractAuthenticationPro import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import static org.springframework.security.oauth2.client.authentication.AuthorizationCodeRequestRedirectFilter.isDefaultRedirectUri; - /** * An implementation of an {@link AbstractAuthenticationProcessingFilter} that handles * the processing of an OAuth 2.0 Authorization Response for the authorization code grant flow. @@ -136,12 +133,16 @@ public class AuthorizationCodeAuthenticationProcessingFilter extends AbstractAut ClientRegistration clientRegistration = this.getClientRegistrationRepository().getRegistrationByClientId( matchingAuthorizationRequest.getClientId()); - // If clientRegistration.redirectUri is the default one (with Uri template variables) - // then use matchingAuthorizationRequest.redirectUri instead - if (isDefaultRedirectUri(clientRegistration)) { - clientRegistration = new ClientRegistrationBuilderWithUriOverrides( - clientRegistration, matchingAuthorizationRequest.getRedirectUri()).build(); - } + // The clientRegistration.redirectUri may contain Uri template variables, whether it's configured by + // the user or configured by default. In these cases, the redirectUri will be expanded and ultimately changed + // (by AuthorizationCodeRequestRedirectFilter) before setting it in the authorization request. + // The resulting redirectUri used for the authorization request and saved within the AuthorizationRequestRepository + // MUST BE the same one used to complete the authorization code flow. + // Therefore, we'll create a copy of the clientRegistration and override the redirectUri + // with the one contained in matchingAuthorizationRequest. + clientRegistration = new ClientRegistration.Builder(clientRegistration) + .redirectUri(matchingAuthorizationRequest.getRedirectUri()) + .build(); AuthorizationCodeAuthorizationResponseAttributes authorizationCodeResponseAttributes = this.authorizationCodeResponseConverter.apply(request); @@ -203,24 +204,4 @@ public class AuthorizationCodeAuthenticationProcessingFilter extends AbstractAut throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } } - - private static class ClientRegistrationBuilderWithUriOverrides extends ClientRegistration.Builder { - - private ClientRegistrationBuilderWithUriOverrides(ClientRegistration clientRegistration, String redirectUri) { - super(clientRegistration.getClientId()); - this.clientSecret(clientRegistration.getClientSecret()); - this.clientAuthenticationMethod(clientRegistration.getClientAuthenticationMethod()); - this.authorizedGrantType(clientRegistration.getAuthorizedGrantType()); - this.redirectUri(redirectUri); - if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) { - this.scopes(clientRegistration.getScopes().stream().toArray(String[]::new)); - } - this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()); - this.tokenUri(clientRegistration.getProviderDetails().getTokenUri()); - this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoUri()); - this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri()); - this.clientName(clientRegistration.getClientName()); - this.clientAlias(clientRegistration.getClientAlias()); - } - } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeRequestRedirectFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeRequestRedirectFilter.java index 2118c83450..d6819dd148 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeRequestRedirectFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeRequestRedirectFilter.java @@ -32,6 +32,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URI; +import java.util.HashMap; +import java.util.Map; import static org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProcessingFilter.AUTHORIZE_BASE_URI; @@ -61,7 +63,6 @@ public class AuthorizationCodeRequestRedirectFilter extends OncePerRequestFilter public static final String AUTHORIZATION_BASE_URI = "/oauth2/authorization/code"; private static final String CLIENT_ALIAS_VARIABLE_NAME = "clientAlias"; private static final String AUTHORIZATION_URI = AUTHORIZATION_BASE_URI + "/{" + CLIENT_ALIAS_VARIABLE_NAME + "}"; - private static final String DEFAULT_REDIRECT_URI_TEMPLATE = "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"; private final AntPathRequestMatcher authorizationRequestMatcher; private final ClientRegistrationRepository clientRegistrationRepository; private final AuthorizationRequestUriBuilder authorizationUriBuilder; @@ -114,12 +115,7 @@ public class AuthorizationCodeRequestRedirectFilter extends OncePerRequestFilter throw new IllegalArgumentException("Invalid Client Identifier (Alias): " + clientAlias); } - String redirectUriStr; - if (isDefaultRedirectUri(clientRegistration)) { - redirectUriStr = this.expandDefaultRedirectUri(request, clientRegistration); - } else { - redirectUriStr = clientRegistration.getRedirectUri(); - } + String redirectUriStr = this.expandRedirectUri(request, clientRegistration); AuthorizationRequestAttributes authorizationRequestAttributes = AuthorizationRequestAttributes.withAuthorizationCode() @@ -145,15 +141,16 @@ public class AuthorizationCodeRequestRedirectFilter extends OncePerRequestFilter response.sendError(HttpServletResponse.SC_BAD_REQUEST, failed.getMessage()); } - static boolean isDefaultRedirectUri(ClientRegistration clientRegistration) { - return DEFAULT_REDIRECT_URI_TEMPLATE.equals(clientRegistration.getRedirectUri()); - } + private String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration) { + Map uriVariables = new HashMap<>(); + uriVariables.put("scheme", request.getScheme()); + uriVariables.put("serverName", request.getServerName()); + uriVariables.put("serverPort", String.valueOf(request.getServerPort())); + uriVariables.put("baseAuthorizeUri", AUTHORIZE_BASE_URI); + uriVariables.put("clientAlias", clientRegistration.getClientAlias()); - private String expandDefaultRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration) { - return UriComponentsBuilder.fromUriString(DEFAULT_REDIRECT_URI_TEMPLATE) - .buildAndExpand(request.getScheme(), request.getServerName(), request.getServerPort(), - AUTHORIZE_BASE_URI, clientRegistration.getClientAlias()) - .encode() + return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()) + .buildAndExpand(uriVariables) .toUriString(); } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java index 4195321060..a5c564fb7f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java @@ -195,6 +195,23 @@ public class ClientRegistration { this.clientAlias(clientRegistrationProperties.getClientAlias()); } + public Builder(ClientRegistration clientRegistration) { + this(clientRegistration.getClientId()); + this.clientSecret(clientRegistration.getClientSecret()); + this.clientAuthenticationMethod(clientRegistration.getClientAuthenticationMethod()); + this.authorizedGrantType(clientRegistration.getAuthorizedGrantType()); + this.redirectUri(clientRegistration.getRedirectUri()); + if (!CollectionUtils.isEmpty(clientRegistration.getScopes())) { + this.scopes(clientRegistration.getScopes().stream().toArray(String[]::new)); + } + this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()); + this.tokenUri(clientRegistration.getProviderDetails().getTokenUri()); + this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoUri()); + this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri()); + this.clientName(clientRegistration.getClientName()); + this.clientAlias(clientRegistration.getClientAlias()); + } + public Builder clientSecret(String clientSecret) { this.clientSecret = clientSecret; return this;