keycloak-uncached

Details

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) {