Skip to content

Commit d17b23f

Browse files
author
Jaskanwal Pawar
committed
Request cache only saves requests with form_redirect_uri if it's valid
- A valid/approved form_redirect_uri value has the same host as the receiving UAA server. [#158222161] https://www.pivotaltracker.com/story/show/158222161
1 parent 57a15df commit d17b23f

File tree

5 files changed

+61
-19
lines changed

5 files changed

+61
-19
lines changed

server/src/main/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,17 @@ public static String getRequestPath(HttpServletRequest request) {
219219
String path = String.format("%s%s", servletPath, pathInfo);
220220
return path;
221221
}
222+
223+
public static boolean uriHasMatchingHost(String uri, String hostname) {
224+
if (uri == null) {
225+
return false;
226+
}
227+
228+
try {
229+
URL url = new URL(uri);
230+
return hostname.equals(url.getHost());
231+
} catch (MalformedURLException e) {
232+
return false;
233+
}
234+
}
222235
}

server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717

1818
import org.apache.commons.logging.Log;
1919
import org.apache.commons.logging.LogFactory;
20+
import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
2021
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
2122

2223
import javax.servlet.http.HttpServletRequest;
2324
import javax.servlet.http.HttpServletResponse;
24-
import java.net.MalformedURLException;
25-
import java.net.URL;
2625

2726
public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
2827
public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
@@ -40,23 +39,10 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
4039
if (redirectAttribute !=null) {
4140
logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
4241
return (String) redirectAttribute;
43-
} else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
42+
} else if (UaaUrlUtils.uriHasMatchingHost(redirectFormParam, request.getServerName())) {
4443
return redirectFormParam;
4544
} else {
4645
return super.determineTargetUrl(request, response);
4746
}
4847
}
49-
50-
private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
51-
if (redirectUri == null) {
52-
return false;
53-
}
54-
55-
try {
56-
URL url = new URL(redirectUri);
57-
return request.getServerName().equals(url.getHost());
58-
} catch (MalformedURLException e) {
59-
return false;
60-
}
61-
}
6248
}

server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCache.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ protected boolean shouldSaveFormRedirectParameter(HttpServletRequest request) {
9292
if (StringUtils.isEmpty(formRedirect)) {
9393
return false;
9494
}
95-
95+
if (!UaaUrlUtils.uriHasMatchingHost(formRedirect, request.getServerName())) {
96+
return false;
97+
}
9698
if (hasSavedRequest(request)) {
9799
return false;
98100
}

server/src/test/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtilsTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
import static org.hamcrest.CoreMatchers.is;
3333
import static org.hamcrest.Matchers.equalTo;
3434
import static org.junit.Assert.assertEquals;
35+
import static org.junit.Assert.assertFalse;
3536
import static org.junit.Assert.assertNotNull;
3637
import static org.junit.Assert.assertThat;
38+
import static org.junit.Assert.assertTrue;
3739
import static org.junit.Assert.fail;
3840

3941
public class UaaUrlUtilsTest {
@@ -360,6 +362,19 @@ public void test_validate_invalid_redirect_uri() {
360362
validateRedirectUri(convertToHttps(invalidHttpWildCardUrls), false);
361363
}
362364

365+
@Test
366+
public void testUriHasMatchingHost() {
367+
assertTrue(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "test.com"));
368+
assertTrue(UaaUrlUtils.uriHasMatchingHost("http://subdomain.test.com/test", "subdomain.test.com"));
369+
assertTrue(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "1.2.3.4"));
370+
371+
assertFalse(UaaUrlUtils.uriHasMatchingHost(null, "test.com"));
372+
assertFalse(UaaUrlUtils.uriHasMatchingHost("http://not-test.com/test", "test.com"));
373+
assertFalse(UaaUrlUtils.uriHasMatchingHost("not-valid-url", "test.com"));
374+
assertFalse(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "test.com"));
375+
assertFalse(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "1.2.3.4"));
376+
}
377+
363378
private void validateRedirectUri(List<String> urls, boolean result) {
364379
Map<String, String> failed = getFailedUrls(urls, result);
365380
if (!failed.isEmpty()) {

server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCacheTests.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
import org.springframework.security.web.savedrequest.SavedRequest;
2929

3030
import javax.servlet.FilterChain;
31+
import javax.servlet.ServletException;
3132
import javax.servlet.ServletResponse;
33+
import javax.servlet.http.HttpServletRequest;
3234
import javax.servlet.http.HttpSession;
35+
import java.io.IOException;
36+
import java.net.MalformedURLException;
37+
import java.net.URL;
3338

3439
import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.FORM_REDIRECT_PARAMETER;
3540
import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.SAVED_REQUEST_SESSION_ATTRIBUTE;
@@ -38,6 +43,7 @@
3843
import static org.junit.Assert.assertFalse;
3944
import static org.junit.Assert.assertNotNull;
4045
import static org.junit.Assert.assertTrue;
46+
import static org.mockito.ArgumentMatchers.any;
4147
import static org.mockito.Matchers.anyObject;
4248
import static org.mockito.Matchers.anyString;
4349
import static org.mockito.Mockito.mock;
@@ -103,6 +109,7 @@ public void filter_saves_when_needed() throws Exception {
103109
request.setPathInfo("/login.do");
104110
request.setRequestURI("/login.do");
105111
request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
112+
request.setServerName(new URL(redirectUri).getHost());
106113
assertTrue(cache.shouldSaveFormRedirectParameter(request));
107114
ServletResponse response = new MockHttpServletResponse();
108115

@@ -145,8 +152,11 @@ public void saveFormRedirectRequest_GET_Method() throws Exception {
145152

146153
@Test
147154
public void saveFormRedirectRequest() throws Exception {
155+
String redirectUri = "http://login";
148156
request.setSession(session);
149-
request.setParameter(FORM_REDIRECT_PARAMETER, "http://login");
157+
request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
158+
request.setServerName(new URL(redirectUri).getHost());
159+
150160
spy.saveRequest(request, new MockHttpServletResponse());
151161
verify(spy).saveClientRedirect(request, request.getParameter(FORM_REDIRECT_PARAMETER));
152162
}
@@ -169,14 +179,19 @@ public void only_save_for_POST_calls() {
169179
}
170180

171181
@Test
172-
public void should_save_condition_works() {
182+
public void should_save_condition_works() throws MalformedURLException {
173183
assertFalse(cache.shouldSaveFormRedirectParameter(request));
184+
174185
request.setPathInfo("/login.do");
175186
assertFalse(cache.shouldSaveFormRedirectParameter(request));
187+
176188
request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
189+
request.setServerName(new URL(redirectUri).getHost());
177190
assertTrue(cache.shouldSaveFormRedirectParameter(request));
191+
178192
request.setSession(session);
179193
assertTrue(cache.shouldSaveFormRedirectParameter(request));
194+
180195
ClientRedirectSavedRequest savedRequest = new ClientRedirectSavedRequest(request, redirectUri);
181196
session.setAttribute(SAVED_REQUEST_SESSION_ATTRIBUTE, savedRequest);
182197
assertFalse(cache.shouldSaveFormRedirectParameter(request));
@@ -215,5 +230,16 @@ public void saved_request_matcher() {
215230

216231
}
217232

233+
@Test
234+
public void unapprovedFormRedirectRequestDoesNotSave() throws IOException, ServletException {
235+
request.setPathInfo("/login.do");
236+
request.setRequestURI("/login.do");
237+
request.setMethod(HttpMethod.POST.name());
238+
request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
239+
request.setServerName("not-test.com");
240+
241+
spy.doFilter(request, new MockHttpServletResponse(), mock(FilterChain.class));
218242

243+
verify(spy, never()).saveClientRedirect(any(HttpServletRequest.class), anyString());
244+
}
219245
}

0 commit comments

Comments
 (0)