diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index c61bdd0..052c048 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -26,6 +26,7 @@ import org.keycloak.services.Urls;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -75,6 +76,10 @@ public class RedirectUtils {
}
private static String verifyRedirectUri(UriInfo uriInfo, String rootUrl, String redirectUri, RealmModel realm, Set<String> validRedirects, boolean requireRedirectUri) {
+
+ if (redirectUri != null)
+ redirectUri = normalizeUrl(redirectUri);
+
if (redirectUri == null) {
if (!requireRedirectUri) {
redirectUri = getSingleValidRedirectUri(validRedirects);
@@ -170,4 +175,12 @@ public class RedirectUtils {
return validRedirect;
}
+ private static String normalizeUrl(String url) {
+ try {
+ URI uri = new URI(url);
+ return uri.normalize().toString();
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Invalid URL syntax: " + e.getMessage());
+ }
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
index 31c1055..fdda242 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
@@ -216,8 +216,8 @@ public class AccountFormServiceTest extends AbstractTestRealmKeycloakTest {
profilePage.open();
loginPage.login("test-user@localhost", "password");
- driver.navigate().to(profilePage.getPath() + "?referrer=test-app&referrer_uri=http://localhost:8180/auth/realms/master/app/auth/test%2Ffkrenu%22%3E%3Cscript%3Ealert%281%29%3C%2fscript%3E");
- Assert.assertTrue(profilePage.isCurrent());
+ driver.navigate().to(profilePage.getPath() + "?referrer=test-app&referrer_uri=http%3A%2F%2Flocalhost%3A8180%2Fauth%2Frealms%2Fmaster%2Fapp%2Fauth%2Ftest%2Ffkrenu%3Fq%3D%2522%253E%253Cscript%253Ealert%25281%2529%253C%252fscript%253E");
+ profilePage.assertCurrent();
assertFalse(driver.getPageSource().contains("<script>alert"));
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
index 8afda1b..73ffc22 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
@@ -165,6 +165,14 @@ public class OAuthRedirectUriTest extends AbstractKeycloakTest {
}
@Test
+ public void testRelativeUri() throws IOException {
+ oauth.redirectUri("/foo/../bar");
+ oauth.openLoginForm();
+ Assert.assertTrue(errorPage.isCurrent());
+ Assert.assertEquals("Invalid parameter: redirect_uri", errorPage.getError());
+ }
+
+ @Test
public void testFileUri() throws IOException {
oauth.redirectUri("file://test");
oauth.openLoginForm();