keycloak-uncached

proxy headers

11/25/2014 6:13:11 PM

Details

diff --git a/docbook/reference/en/en-US/modules/proxy.xml b/docbook/reference/en/en-US/modules/proxy.xml
index 62848ec..f5f6053 100755
--- a/docbook/reference/en/en-US/modules/proxy.xml
+++ b/docbook/reference/en/en-US/modules/proxy.xml
@@ -274,4 +274,46 @@ $ java -jar bin/launcher.jar [your-config.json]
         </section>
         </section>
     </section>
+    <section>
+        <title>Keycloak Identity Headers</title>
+        <para>
+            When forwarding requests to the proxied server, Keycloak Proxy will set some additional headers with values from the
+            OIDC identity token it received for authentication.
+            <variablelist>
+                <varlistentry>
+                    <term>KEYCLOAK_SUBJECT</term>
+                    <listitem>
+                        <para>
+                            User id. Corresponds to JWT <literal>sub</literal> and will be the user id Keycloak uses to store
+                            this user.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_USERNAME</term>
+                    <listitem>
+                        <para>
+                            Username. Corresponds to JWT <literal>preferred_username</literal>
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_EMAIL</term>
+                    <listitem>
+                        <para>
+                            Email address of user if set.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_NAME</term>
+                    <listitem>
+                        <para>
+                            Full name of user if set.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+    </section>
 </chapter>
\ No newline at end of file

pom.xml 4(+2 -2)

diff --git a/pom.xml b/pom.xml
index 1bf8595..08994f0 100755
--- a/pom.xml
+++ b/pom.xml
@@ -18,8 +18,8 @@
         <keycloak.apache.httpcomponents.version>4.2.1</keycloak.apache.httpcomponents.version>
         <resteasy.version>2.3.7.Final</resteasy.version>
         <resteasy.version.latest>3.0.9.Final</resteasy.version.latest>
+        <!-- <undertow.version>1.1.0.Final</undertow.version> -->
         <undertow.version>1.0.15.Final</undertow.version>
-<!--        <picketlink.version>2.7.0.CR1-20140924</picketlink.version>  -->
         <picketlink.version>2.7.0.CR2</picketlink.version>
         <picketbox.ldap.version>1.0.2.Final</picketbox.ldap.version>
         <mongo.driver.version>2.11.3</mongo.driver.version>
@@ -108,7 +108,7 @@
         <module>events</module>
         <module>model</module>
         <module>integration</module>
-        <module>proxy</module>
+        <module>proxy/proxy-server</module>
         <module>picketlink</module>
         <module>federation</module>
         <module>services</module>
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
index 75b19e2..d0ff18b 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
@@ -2,7 +2,9 @@ package org.keycloak.proxy;
 
 import io.undertow.server.HttpHandler;
 import io.undertow.server.HttpServerExchange;
+import io.undertow.util.HttpString;
 import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
+import org.keycloak.representations.IDToken;
 
 import java.util.Collection;
 
@@ -11,6 +13,10 @@ import java.util.Collection;
  * @version $Revision: 1 $
  */
 public class ConstraintAuthorizationHandler implements HttpHandler {
+    public static final HttpString KEYCLOAK_SUBJECT = new HttpString("KEYCLOAK_SUBJECT");
+    public static final HttpString KEYCLOAK_USERNAME = new HttpString("KEYCLOAK_USERNAME");
+    public static final HttpString KEYCLOAK_EMAIL = new HttpString("KEYCLOAK_EMAIL");
+    public static final HttpString KEYCLOAK_NAME = new HttpString("KEYCLOAK_NAME");
 
     protected HttpHandler next;
     protected String errorPage;
@@ -25,13 +31,13 @@ public class ConstraintAuthorizationHandler implements HttpHandler {
         KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
         SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY);
         if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) {
-            next.handleRequest(exchange);
+            authenticatedRequest(account, exchange);
             return;
         }
         if (match != null) {
             for (String role : match.getRequiredRoles()) {
                 if (account.getRoles().contains(role)) {
-                    next.handleRequest(exchange);
+                    authenticatedRequest(account, exchange);
                     return;
                 }
             }
@@ -48,4 +54,23 @@ public class ConstraintAuthorizationHandler implements HttpHandler {
         exchange.endExchange();
 
     }
+
+    public void authenticatedRequest(KeycloakUndertowAccount account, HttpServerExchange exchange) throws Exception {
+        if (account != null) {
+            IDToken idToken = account.getKeycloakSecurityContext().getIdToken();
+            if (idToken.getSubject() != null) {
+                exchange.getRequestHeaders().put(KEYCLOAK_SUBJECT, idToken.getSubject());
+            }
+            if (idToken.getPreferredUsername() != null) {
+                exchange.getRequestHeaders().put(KEYCLOAK_USERNAME, idToken.getPreferredUsername());
+            }
+            if (idToken.getEmail() != null) {
+                exchange.getRequestHeaders().put(KEYCLOAK_EMAIL, idToken.getEmail());
+            }
+            if (idToken.getName() != null) {
+                exchange.getRequestHeaders().put(KEYCLOAK_NAME, idToken.getName());
+            }
+        }
+        next.handleRequest(exchange);
+    }
 }
diff --git a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java b/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
index 0c27c20..3c55b80 100755
--- a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
+++ b/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
@@ -70,6 +70,7 @@ import java.io.OutputStream;
 import java.net.URI;
 import java.net.URL;
 import java.security.Principal;
+import java.util.Enumeration;
 import java.util.regex.Matcher;
 
 /**
@@ -100,8 +101,11 @@ public class ProxyTest {
             req.getSession().setAttribute("counter", new Integer(count.intValue() + 1));
             stream.write(("count:"+count).getBytes());
 
-
-
+            Enumeration<String> headers = req.getHeaderNames();
+            while (headers.hasMoreElements()) {
+                String name = headers.nextElement();
+                System.out.println(name +": " + req.getHeader(name));
+            }
         }
         @Override
         protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {