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 2abb3bb..fd463ad 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 ca0da18..97ac662 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) {