diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanism.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanism.java index 2abb3bbd06..fd463ada44 100644 --- a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanism.java +++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanism.java @@ -19,6 +19,7 @@ package org.keycloak.adapters.saml.elytron; import java.net.URI; import java.util.Map; +import java.util.regex.Pattern; import javax.security.auth.callback.CallbackHandler; @@ -142,14 +143,23 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat exchange.getResponse().setStatus(302); } + private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:"); + static void sendRedirect(final ElytronHttpFacade exchange, final String location) { - // TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better - // handle this. - URI uri = exchange.getURI(); - String path = uri.getPath(); - String relativePath = exchange.getRequest().getRelativePath(); - String contextPath = path.substring(0, path.indexOf(relativePath)); - String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location; - exchange.getResponse().setHeader("Location", loc); + if (location == null) { + LOGGER.warn("Logout page not set."); + exchange.getResponse().setStatus(302); + return; + } + if (PROTOCOL_PATTERN.matcher(location).find()) { + exchange.getResponse().setHeader("Location", location); + } else { + URI uri = exchange.getURI(); + String path = uri.getPath(); + String relativePath = exchange.getRequest().getRelativePath(); + String contextPath = path.substring(0, path.indexOf(relativePath)); + String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location; + exchange.getResponse().setHeader("Location", loc); + } } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java index ca0da18309..97ac662e85 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java @@ -103,6 +103,22 @@ public class IOUtil { } } + /** + * Modifies attribute value according to the given regex (first occurrence) iff + * there are following conditions accomplished: + * + * - exactly one node is found within the document + * - the attribute of the node exists + * - the regex is found in the value of the attribute + * + * Otherwise there is nothing changed. + * + * @param doc + * @param tagName + * @param attributeName + * @param regex + * @param replacement + */ public static void modifyDocElementAttribute(Document doc, String tagName, String attributeName, String regex, String replacement) { NodeList nodes = doc.getElementsByTagName(tagName); if (nodes.getLength() != 1) { @@ -115,7 +131,7 @@ public class IOUtil { log.warn("Not able to find attribute " + attributeName + " within element: " + tagName); return; } - node.setTextContent(node.getTextContent().replace(regex, replacement)); + node.setTextContent(node.getTextContent().replaceFirst(regex, replacement)); } public static void removeNodeByAttributeValue(Document doc, String parentTag, String tagName, String attributeName, String value){ @@ -141,6 +157,20 @@ public class IOUtil { } } + /** + * Modifies element text value according to the given regex (first occurrence) iff + * there are following conditions accomplished: + * + * - exactly one node is found within the document + * - the regex is found in the text content of the element + * + * Otherwise there is nothing changed. + * + * @param doc + * @param tagName + * @param regex + * @param replacement + */ public static void modifyDocElementValue(Document doc, String tagName, String regex, String replacement) { NodeList nodes = doc.getElementsByTagName(tagName); if (nodes.getLength() != 1) { @@ -154,7 +184,7 @@ public class IOUtil { return; } - node.setTextContent(node.getTextContent().replace(regex, replacement)); + node.setTextContent(node.getTextContent().replaceFirst(regex, replacement)); } public static void setDocElementAttributeValue(Document doc, String tagName, String attributeName, String value) {