Skip to content

Commit e3b53b4

Browse files
committed
Fix OIDC redirect handling after login using RequestCache
1 parent 9a883cd commit e3b53b4

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

core/src/main/java/org/fao/geonet/kernel/security/openidconnect/GeonetworkOAuth2LoginAuthenticationFilter.java

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
3838
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
3939
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
40+
import org.springframework.security.web.savedrequest.RequestCache;
41+
import org.springframework.security.web.savedrequest.SavedRequest;
4042
import org.springframework.util.MultiValueMap;
4143
import org.springframework.web.util.UriComponentsBuilder;
4244

@@ -59,6 +61,9 @@ public class GeonetworkOAuth2LoginAuthenticationFilter extends OAuth2LoginAuthen
5961
@Autowired
6062
OAuth2SecurityProviderUtil oAuth2SecurityProviderUtil;
6163

64+
@Autowired
65+
RequestCache requestCache;
66+
6267
public GeonetworkOAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) {
6368
super(clientRegistrationRepository, authorizedClientService);
6469
}
@@ -117,24 +122,54 @@ protected void successfulAuthentication(HttpServletRequest request,
117122
try{
118123
SecurityContextHolder.getContext().setAuthentication(authResult);
119124

125+
// Use Spring Security's SavedRequest mechanism to get the original request URL
126+
// The request should have been saved by GeonetworkOidcPreAuthActionsLoginFilter before
127+
// redirecting the user to the OIDC provider login
128+
String redirectURL = null;
129+
130+
if (requestCache != null) {
131+
SavedRequest savedRequest = requestCache.getRequest(request, response);
132+
if (savedRequest != null) {
133+
redirectURL = savedRequest.getRedirectUrl();
134+
Log.debug(Geonet.SECURITY, "Retrieved original request from SavedRequest: " + redirectURL);
135+
} else {
136+
Log.debug(Geonet.SECURITY, "No SavedRequest found in RequestCache");
137+
}
138+
139+
if (redirectURL != null) {
140+
Log.info(Geonet.SECURITY, "Redirecting to " + redirectURL);
120141

121-
//cf GN keycloak
122-
String redirectURL = findQueryParameter(request, "redirectUrl");
123-
if (redirectURL != null) {
124-
try {
125-
URI redirectUri = new URI(redirectURL);
126-
if (redirectUri != null && !redirectUri.isAbsolute()) {
127-
response.sendRedirect(redirectUri.toString());
128-
} else {
129-
// If the redirect url ends up being null or absolute url then lets redirect back to the context home.
130-
Log.warning(Geonet.SECURITY, "Failed to perform login redirect to '" + redirectURL + "'. Redirected to context home");
142+
// Removing original request, since we want to
143+
// retain current headers.
144+
// If request remains in cache, requestCacheFilter
145+
// will reinstate the original headers and we don't
146+
// want it.
147+
requestCache.removeRequest(request, response);
148+
149+
response.sendRedirect(redirectURL);
150+
}
151+
} else {
152+
Log.debug(Geonet.SECURITY, "RequestCache is not available");
153+
154+
redirectURL = findQueryParameter(request, "redirectUrl");
155+
if (redirectURL != null) {
156+
Log.debug(Geonet.SECURITY, "Retrieved redirect URL from query parameter: " + redirectURL);
157+
158+
try {
159+
URI redirectUri = new URI(redirectURL);
160+
if (!redirectUri.isAbsolute()) {
161+
response.sendRedirect(redirectUri.toString());
162+
} else {
163+
// If the redirect url ends up being null or absolute url then lets redirect back to the context home.
164+
Log.warning(Geonet.SECURITY, "Failed to perform login redirect to '" + redirectURL + "'. Redirected to context home");
165+
response.sendRedirect(request.getContextPath());
166+
}
167+
} catch (URISyntaxException e) {
131168
response.sendRedirect(request.getContextPath());
132169
}
133-
} catch (URISyntaxException e) {
170+
} else {
134171
response.sendRedirect(request.getContextPath());
135172
}
136-
} else {
137-
response.sendRedirect(request.getContextPath());
138173
}
139174

140175
// Set users preferred locale if it exists. - cf. keycloak

core/src/main/java/org/fao/geonet/kernel/security/openidconnect/GeonetworkOidcPreAuthActionsLoginFilter.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,18 @@
2222
*/
2323
package org.fao.geonet.kernel.security.openidconnect;
2424

25-
import org.fao.geonet.Constants;
2625
import org.springframework.beans.factory.annotation.Autowired;
2726
import org.springframework.security.authentication.AnonymousAuthenticationToken;
2827
import org.springframework.security.core.context.SecurityContextHolder;
2928
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
3029
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
30+
import org.springframework.security.web.savedrequest.RequestCache;
3131

3232
import javax.servlet.*;
3333
import javax.servlet.http.HttpServletRequest;
3434
import javax.servlet.http.HttpServletResponse;
3535
import javax.servlet.http.HttpSession;
3636
import java.io.IOException;
37-
import java.net.URLEncoder;
3837
import org.apache.commons.lang3.StringUtils;
3938
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
4039
import org.springframework.web.context.ServletContextAware;
@@ -57,6 +56,8 @@ public class GeonetworkOidcPreAuthActionsLoginFilter implements Filter, Servlet
5756
@Autowired
5857
private ClientRegistrationRepository clientRegistrationRepository;
5958

59+
@Autowired
60+
private RequestCache requestCache;
6061

6162
/**
6263
* The servlet context parameter name that contains the excluded URL paths.
@@ -127,11 +128,12 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
127128
.anyMatch(matcher -> matcher.matches(servletRequest));
128129

129130
if (!isAuthenticated && !isLoginRequest && !isPublicEndpoint && !isBearerTokenAccess) {
130-
String returningUrl = requestUri +
131-
(servletRequest.getQueryString() == null ? "" : "?" + servletRequest.getQueryString());
131+
// Save the original request so it can be retrieved after successful authentication
132+
if (requestCache != null) {
133+
requestCache.saveRequest(servletRequest, servletResponse);
134+
}
132135

133-
String redirectUrl = loginPath + "?redirectUrl=" + URLEncoder.encode(returningUrl, Constants.ENCODING);
134-
servletResponse.sendRedirect(redirectUrl);
136+
servletResponse.sendRedirect(loginPath);
135137
return;
136138
}
137139

0 commit comments

Comments
 (0)