diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java b/server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java index f277bbfebe3..c705f9bf245 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java @@ -47,7 +47,12 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo String relayState = UaaStringUtils.getCleanedUserControlString(request.getParameter(Saml2ParameterNames.RELAY_STATE), UaaStringUtils.EMPTY_STRING); if (UaaStringUtils.hasText(relayState) && UaaUrlUtils.isUrl(relayState)) { log.debug("Redirecting to relayState URI: {}", relayState); - this.getRedirectStrategy().sendRedirect(request, response, relayState); + java.util.List samlRelayStateWhitelist = java.util.Optional.ofNullable( + org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder.get().getConfig().getLinks().getLogout().getWhitelist() + ).orElse(java.util.Collections.emptyList()); + String fallbackUrl = this.getDefaultTargetUrl(); + String matchingRedirectUri = UaaUrlUtils.findMatchingRedirectUri(samlRelayStateWhitelist, relayState, fallbackUrl); + this.getRedirectStrategy().sendRedirect(request, response, matchingRedirectUri); } else { super.onAuthenticationSuccess(request, response, authentication); } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java index 2d605c0d240..eeffd9e3a3c 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java @@ -76,7 +76,7 @@ void invalidFormRedirectIsNotReturned() { } @Test - void onAuthenticationSuccess_noSavedRequest_hasRelayStateUrl() throws Exception { + void onAuthenticationSuccess_noSavedRequest_hasRelayStateUrl_notWhitelisted() throws Exception { String redirectUri = "https://test.com/test2"; request.setParameter(Saml2ParameterNames.RELAY_STATE, redirectUri); @@ -84,7 +84,27 @@ void onAuthenticationSuccess_noSavedRequest_hasRelayStateUrl() throws Exception var authentication = mock(Authentication.class); handler.onAuthenticationSuccess(request, response, authentication); + assertThat(response.getRedirectedUrl()).isEqualTo("/"); + } + + @Test + void onAuthenticationSuccess_noSavedRequest_hasRelayStateUrl_whitelisted() throws Exception { + String redirectUri = "https://test.com/test2"; + request.setParameter(Saml2ParameterNames.RELAY_STATE, redirectUri); + + org.cloudfoundry.identity.uaa.zone.IdentityZone zone = org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder.get(); + zone.getConfig().getLinks().getLogout().setWhitelist(java.util.List.of("https://test.com/test2")); + org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder.set(zone); + + var response = new MockHttpServletResponse(); + var authentication = mock(Authentication.class); + handler.onAuthenticationSuccess(request, response, authentication); + assertThat(response.getRedirectedUrl()).isEqualTo(redirectUri); + + // clean up + zone.getConfig().getLinks().getLogout().setWhitelist(null); + org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder.clear(); } @Test diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/SamlLoginIT.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/SamlLoginIT.java index c526d4657e6..861d91e2ce7 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/SamlLoginIT.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/SamlLoginIT.java @@ -779,7 +779,7 @@ void relayStateRedirectFromIdpInitiatedLogin() { webDriver.findElement(By.xpath(samlServerConfig.getLoginPromptXpathExpr())); sendCredentials(testAccounts.getUserName(), testAccounts.getPassword()); Page.assertThatUrlEventuallySatisfies(webDriver, - assertUrl -> assertUrl.startsWith("https://www.google.com")); + assertUrl -> assertUrl.startsWith(baseUrl)); webDriver.get("%s/logout.do".formatted(baseUrl)); } @@ -1228,7 +1228,7 @@ void backportFrom77RelayTest() { sendCredentials(testAccounts.getUserName(), "koala"); Page.assertThatUrlEventuallySatisfies(webDriver, - assertUrl -> assertUrl.startsWith("https://www.google.com")); + assertUrl -> assertUrl.startsWith(zoneUrl)); webDriver.get(baseUrl + "/logout.do"); webDriver.get(zoneUrl + "/logout.do"); }