keycloak-uncached

Merge pull request #283 from patriot1burke/master adapter

3/11/2014 7:08:23 PM

Changes

Details

diff --git a/distribution/appliance-dist/src/main/xslt/standalone.xsl b/distribution/appliance-dist/src/main/xslt/standalone.xsl
index 8f8011b..64fda33 100755
--- a/distribution/appliance-dist/src/main/xslt/standalone.xsl
+++ b/distribution/appliance-dist/src/main/xslt/standalone.xsl
@@ -38,6 +38,18 @@
         </xsl:copy>
     </xsl:template>
 
+    <xsl:template match="node()[name(.)='security-domains']">
+        <xsl:copy>
+            <xsl:apply-templates select="node()[name(.)='security-domain']"/>
+            <security-domain name="keycloak">
+                <authentication>
+                    <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule" flag="required"/>
+                </authentication>
+            </security-domain>
+        </xsl:copy>
+    </xsl:template>
+
+
     <!-- for some reason, Wildfly 8 final decided to turn off management-native which means jboss-as-maven-plugin no
          longer works -->
     <xsl:template match="node()[name(.)='management-interfaces']">
diff --git a/distribution/as7-adapter-zip/assembly.xml b/distribution/as7-adapter-zip/assembly.xml
index f4b56a1..6a507fd 100755
--- a/distribution/as7-adapter-zip/assembly.xml
+++ b/distribution/as7-adapter-zip/assembly.xml
@@ -12,6 +12,7 @@
             <excludes>
                 <exclude>org/keycloak/keycloak-undertow-adapter/**</exclude>
                 <exclude>org/keycloak/keycloak-wildfly-subsystem/**</exclude>
+                <exclude>org/keycloak/keycloak-wildfly-adapter/**</exclude>
             </excludes>
             <outputDirectory>modules</outputDirectory>
         </fileSet>
diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml
index 16694d4..8503475 100755
--- a/distribution/modules/build.xml
+++ b/distribution/modules/build.xml
@@ -59,6 +59,10 @@
             <maven-resource group="org.keycloak" artifact="keycloak-adapter-core"/>
         </module-def>
 
+        <module-def name="org.keycloak.keycloak-jboss-adapter-core">
+            <maven-resource group="org.keycloak" artifact="keycloak-jboss-adapter-core"/>
+        </module-def>
+
         <module-def name="org.keycloak.keycloak-as7-adapter">
             <maven-resource group="org.keycloak" artifact="keycloak-as7-adapter"/>
         </module-def>
@@ -67,6 +71,10 @@
             <maven-resource group="org.keycloak" artifact="keycloak-undertow-adapter"/>
         </module-def>
 
+        <module-def name="org.keycloak.keycloak-wildfly-adapter">
+            <maven-resource group="org.keycloak" artifact="keycloak-wildfly-adapter"/>
+        </module-def>
+
         <module-def name="org.keycloak.keycloak-wildfly-subsystem">
             <maven-resource group="org.keycloak" artifact="keycloak-wildfly-subsystem"/>
         </module-def>
diff --git a/distribution/modules/pom.xml b/distribution/modules/pom.xml
index ee3c31f..107a06d 100755
--- a/distribution/modules/pom.xml
+++ b/distribution/modules/pom.xml
@@ -51,6 +51,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jboss-adapter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-as7-adapter</artifactId>
             <version>${project.version}</version>
         </dependency>
@@ -61,6 +66,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-wildfly-adapter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-wildfly-subsystem</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml
new file mode 100755
index 0000000..5ecc097
--- /dev/null
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2010, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-jboss-adapter-core">
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="javax.api"/>
+        <module name="org.jboss.logging"/>
+        <module name="org.picketbox"/>
+        <module name="org.keycloak.keycloak-adapter-core"/>
+        <module name="org.keycloak.keycloak-core"/>
+    </dependencies>
+
+</module>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml
new file mode 100755
index 0000000..a89bac4
--- /dev/null
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2010, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-wildfly-adapter">
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="javax.api"/>
+        <module name="org.bouncycastle"/>
+        <module name="org.codehaus.jackson.jackson-core-asl"/>
+        <module name="org.codehaus.jackson.jackson-mapper-asl"/>
+        <module name="org.codehaus.jackson.jackson-xc"/>
+        <module name="org.apache.httpcomponents" />
+        <module name="javax.servlet.api"/>
+        <module name="org.jboss.logging"/>
+        <module name="io.undertow.core"/>
+        <module name="io.undertow.servlet"/>
+        <module name="org.picketbox"/>
+        <module name="org.keycloak.keycloak-undertow-adapter"/>
+        <module name="org.keycloak.keycloak-adapter-core"/>
+        <module name="org.keycloak.keycloak-core"/>
+    </dependencies>
+
+</module>
diff --git a/docbook/reference/en/en-US/modules/jboss-adapter.xml b/docbook/reference/en/en-US/modules/jboss-adapter.xml
index c6e6597..90dc1cd 100755
--- a/docbook/reference/en/en-US/modules/jboss-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jboss-adapter.xml
@@ -73,6 +73,66 @@ $ unzip keycloak-as7-adapter-dist.zip
 ]]>
 </programlisting>
     </para>
+        <para>
+            Finally, for both AS7, EAP 6.x, and Wildfly installations you must specify a shared keycloak security domain.
+            This security domain should be used with EJBs and other components when you need the security context created
+            in the secured web tier to be propagated to the EJBs (other EE component) you are invoking.  Otherwise
+            this configuration is optional.
+        </para>
+<programlisting><![CDATA[
+<server xmlns="urn:jboss:domain:1.4">
+ <subsystem xmlns="urn:jboss:domain:security:1.2">
+    <security-domains>
+...
+      <security-domain name="keycloak">
+         <authentication>
+           <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
+                         flag="required"/>
+          </authentication>
+      </security-domain>
+    </security-domains>
+]]>
+</programlisting>
+        <para>
+            For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want
+            to annotate it with the @SecurityDomain annotation as follows:
+        </para>
+<programlisting><![CDATA[
+import org.jboss.ejb3.annotation.SecurityDomain;
+import org.jboss.resteasy.annotations.cache.NoCache;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.util.ArrayList;
+import java.util.List;
+
+@Path("customers")
+@Stateless
+@SecurityDomain("keycloak")
+public class CustomerService {
+
+    @EJB
+    CustomerDB db;
+
+    @GET
+    @Produces("application/json")
+    @NoCache
+    @RolesAllowed("db_user")
+    public List<String> getCustomers() {
+        return db.getCustomers();
+    }
+}
+]]>
+</programlisting>
+        <para>
+            We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain
+            annotation when you want to propagate a keycloak security context to the EJB tier.
+        </para>
+
     </section>
     <section>
         <title>Per WAR Configuration</title>
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java
new file mode 100755
index 0000000..4bc9dd4
--- /dev/null
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java
@@ -0,0 +1,19 @@
+package org.keycloak.adapters;
+
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.representations.AccessToken;
+
+import java.security.Principal;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakAccount {
+    Principal getPrincipal();
+    Set<String> getRoles();
+    KeycloakSecurityContext getKeycloakSecurityContext();
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index 5a326b8..d497c0d 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -48,6 +48,7 @@ public class KeycloakDeploymentBuilder {
         deployment.setSslRequired(!adapterConfig.isSslNotRequired());
         deployment.setResourceCredentials(adapterConfig.getCredentials());
         deployment.setPublicClient(adapterConfig.isPublicClient());
+        deployment.setUseResourceRoleMappings(adapterConfig.isUseResourceRoleMappings());
 
         if (adapterConfig.isBearerOnly()) {
             deployment.setBearerOnly(true);
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
index 5ddbc58..6442499 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
@@ -46,6 +46,10 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext 
         return this.token.isActive() && this.token.getIssuedAt() > deployment.getNotBefore();
     }
 
+    public KeycloakDeployment getDeployment() {
+        return deployment;
+    }
+
     public void setDeployment(KeycloakDeployment deployment) {
         this.deployment = deployment;
     }
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
index f0d697c..103098a 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
@@ -8,7 +8,7 @@ import org.keycloak.KeycloakPrincipal;
  * @version $Revision: 1 $
  */
 public abstract class RequestAuthenticator {
-    protected Logger log = Logger.getLogger(RequestAuthenticator.class);
+    protected static Logger log = Logger.getLogger(RequestAuthenticator.class);
 
     protected HttpFacade facade;
     protected KeycloakDeployment deployment;
@@ -33,19 +33,25 @@ public abstract class RequestAuthenticator {
     public AuthOutcome authenticate() {
         log.info("--> authenticate()");
         BearerTokenRequestAuthenticator bearer = createBearerTokenAuthenticator();
+        log.info("try bearer");
         AuthOutcome outcome = bearer.authenticate(facade);
         if (outcome == AuthOutcome.FAILED) {
             challenge = bearer.getChallenge();
+            log.info("Bearer FAILED");
             return AuthOutcome.FAILED;
         } else if (outcome == AuthOutcome.AUTHENTICATED) {
             completeAuthentication(bearer);
+            log.info("Bearer AUTHENTICATED");
             return AuthOutcome.AUTHENTICATED;
         } else if (deployment.isBearerOnly()) {
             challenge = bearer.getChallenge();
+            log.info("NOT_ATTEMPTED: bearer only");
             return AuthOutcome.NOT_ATTEMPTED;
         }
 
+        log.info("try oauth");
         if (isCached()) {
+            log.info("AUTHENTICATED: was cached");
             return AuthOutcome.AUTHENTICATED;
         }
 
diff --git a/integration/as7-eap6/adapter/pom.xml b/integration/as7-eap6/adapter/pom.xml
index ea2c35e..07dc6e3 100755
--- a/integration/as7-eap6/adapter/pom.xml
+++ b/integration/as7-eap6/adapter/pom.xml
@@ -24,6 +24,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jboss-adapter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <version>${keycloak.apache.httpcomponents.version}</version>
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
index 1188e6d..9e211b2 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java
@@ -4,6 +4,7 @@ import org.apache.catalina.Session;
 import org.apache.catalina.authenticator.Constants;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.realm.GenericPrincipal;
+import org.jboss.logging.Logger;
 import org.keycloak.KeycloakPrincipal;
 import org.keycloak.KeycloakSecurityContext;
 import org.keycloak.adapters.KeycloakDeployment;
@@ -22,6 +23,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class CatalinaRequestAuthenticator extends RequestAuthenticator {
+    private static final Logger log = Logger.getLogger(CatalinaRequestAuthenticator.class);
     protected KeycloakAuthenticatorValve valve;
     protected CatalinaUserSessionManagement userSessionManagement;
     protected Request request;
@@ -53,7 +55,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
     @Override
     protected void completeOAuthAuthentication(KeycloakPrincipal skp, RefreshableKeycloakSecurityContext securityContext) {
         Set<String> roles = getRolesFromToken(securityContext);
-        GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skp, roles);
+        GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skp, roles, securityContext);
         Session session = request.getSessionInternal(true);
         session.setPrincipal(principal);
         session.setAuthType("OAUTH");
@@ -66,7 +68,10 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
     @Override
     protected void completeBearerAuthentication(KeycloakPrincipal principal, RefreshableKeycloakSecurityContext securityContext) {
         Set<String> roles = getRolesFromToken(securityContext);
-        Principal generalPrincipal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), principal, roles);
+        for (String role : roles) {
+            log.info("Bearer role: " + role);
+        }
+        Principal generalPrincipal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
         request.setUserPrincipal(generalPrincipal);
         request.setAuthType("KEYCLOAK");
         request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
index 8cfbcb5..f33c463 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
@@ -9,6 +9,8 @@ import org.jboss.security.SecurityContext;
 import org.jboss.security.SecurityContextAssociation;
 import org.jboss.security.SimpleGroup;
 import org.jboss.security.SimplePrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.KeycloakAccount;
 
 import javax.security.auth.Subject;
 import java.security.Principal;
@@ -25,9 +27,24 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class CatalinaSecurityContextHelper {
-    public GenericPrincipal createPrincipal(Realm realm, Principal identity, Collection<String> roleSet) {
+    public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
+        KeycloakAccount account = new KeycloakAccount() {
+            @Override
+            public Principal getPrincipal() {
+                return identity;
+            }
+
+            @Override
+            public Set<String> getRoles() {
+                return roleSet;
+            }
+
+            @Override
+            public KeycloakSecurityContext getKeycloakSecurityContext() {
+                return securityContext;
+            }
+        };
         Subject subject = new Subject();
-        String credentials = "";
         Set<Principal> principals = subject.getPrincipals();
         principals.add(identity);
         Group[] roleSets = getRoleSets(roleSet);
@@ -56,11 +73,11 @@ public class CatalinaSecurityContextHelper {
         principals.add(callerGroup);
         SecurityContext sc = SecurityContextAssociation.getSecurityContext();
         Principal userPrincipal = getPrincipal(subject);
-        sc.getUtil().createSubjectInfo(userPrincipal, credentials, subject);
+        sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
         List<String> rolesAsStringList = new ArrayList<String>();
         rolesAsStringList.addAll(roleSet);
         return new JBossGenericPrincipal(realm, userPrincipal.getName(), null, rolesAsStringList,
-                userPrincipal, null, credentials, null, subject);
+                userPrincipal, null, account, null, subject);
 
     }
 
diff --git a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
index 2ac2ccf..c9a32d6 100755
--- a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
+++ b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
@@ -36,6 +36,7 @@ public class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
 
     private static final ModuleIdentifier KEYCLOAK_AS7_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-as7-adapter");
     private static final ModuleIdentifier KEYCLOAK_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-adapter-core");
+    private static final ModuleIdentifier KEYCLOAK_JBOSS_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-jboss-adapter-core");
     private static final ModuleIdentifier KEYCLOAK_CORE = ModuleIdentifier.create("org.keycloak.keycloak-core");
     //private static final ModuleIdentifier APACHE_HTTPCOMPONENTS = ModuleIdentifier.create("org.apache.httpcomponents");
 
@@ -51,6 +52,7 @@ public class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
 
         moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_AS7_ADAPTER, false, false, true, false));
+        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_JBOSS_CORE_ADAPTER, false, false, false, false));
         moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE_ADAPTER, false, false, false, false));
         moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE, false, false, false, false));
         //moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, APACHE_HTTPCOMPONENTS, false, false, true, false));
diff --git a/integration/jboss-adapter-core/pom.xml b/integration/jboss-adapter-core/pom.xml
new file mode 100755
index 0000000..0d599a5
--- /dev/null
+++ b/integration/jboss-adapter-core/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.0-alpha-3-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-jboss-adapter-core</artifactId>
+    <name>Common JBoss/Wildfly Core Classes</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>3.1.2.GA</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${keycloak.apache.httpcomponents.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.picketbox</groupId>
+            <artifactId>picketbox</artifactId>
+            <version>4.0.20.Final</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java b/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java
new file mode 100755
index 0000000..e3db8c5
--- /dev/null
+++ b/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java
@@ -0,0 +1,100 @@
+package org.keycloak.adapters.jboss;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.callback.ObjectCallback;
+import org.jboss.security.auth.spi.AbstractServerLoginModule;
+import org.keycloak.adapters.KeycloakAccount;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakLoginModule extends AbstractServerLoginModule {
+    protected static Logger log = Logger.getLogger(KeycloakLoginModule.class);
+    protected Set<String> roleSet;
+    protected Principal identity;
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean login() throws LoginException {
+        log.info("KeycloakLoginModule.login()");
+        if (super.login() == true) {
+            log.info("super.login()==true");
+            return true;
+        }
+
+        Object credential = getCredential();
+        if (credential != null && (credential instanceof KeycloakAccount)) {
+            log.info("Found Account");
+            KeycloakAccount account = (KeycloakAccount)credential;
+            roleSet = account.getRoles();
+            identity = account.getPrincipal();
+            sharedState.put("javax.security.auth.login.name", identity);
+            sharedState.put("javax.security.auth.login.password", credential);
+            loginOk = true;
+            return true;
+        }
+
+        // We return false to allow the next module to attempt authentication, maybe a
+        // username and password has been supplied to a web auth.
+        return false;
+    }
+
+
+    @Override
+    protected Principal getIdentity() {
+        return identity;
+    }
+
+    /*
+    @Override
+    protected Group[] getRoleSets() throws LoginException {
+        return new Group[0];
+    }
+    */
+
+    @Override
+    protected Group[] getRoleSets() throws LoginException {
+        //log.info("getRoleSets");
+        SimpleGroup roles = new SimpleGroup("Roles");
+        Group[] roleSets = {roles};
+        for (String role : roleSet) {
+            //log.info("   adding role: " + role);
+            roles.addMember(new SimplePrincipal(role));
+        }
+        return roleSets;
+    }
+
+    protected Object getCredential() throws LoginException {
+        NameCallback nc = new NameCallback("Alias: ");
+        ObjectCallback oc = new ObjectCallback("Credential: ");
+        Callback[] callbacks = { nc, oc };
+
+        try {
+            callbackHandler.handle(callbacks);
+
+            return oc.getCredential();
+        } catch (IOException ioe) {
+            LoginException le = new LoginException();
+            le.initCause(ioe);
+            throw le;
+        } catch (UnsupportedCallbackException uce) {
+            LoginException le = new LoginException();
+            le.initCause(uce);
+            throw le;
+        }
+    }
+
+}
diff --git a/integration/pom.xml b/integration/pom.xml
index f52c6e6..d07f29b 100755
--- a/integration/pom.xml
+++ b/integration/pom.xml
@@ -18,8 +18,10 @@
         <module>adapter-core</module>
         <module>jaxrs-oauth-client</module>
         <module>servlet-oauth-client</module>
+        <module>jboss-adapter-core</module>
         <module>as7-eap6/adapter</module>
         <module>undertow</module>
+        <module>wildfly-adapter</module>
         <module>wildfly-subsystem</module>
         <module>as7-eap-subsystem</module>
         <module>js</module>
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
index 50895c6..4c07480 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
@@ -65,7 +65,7 @@ public class KeycloakServletExtension implements ServletExtension {
         if (is == null) throw new RuntimeException("Unable to find realm config in /WEB-INF/keycloak.json or in keycloak subsystem.");
         KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(is);
         UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement(deployment);
-        final ServletKeycloakAuthMech mech = new ServletKeycloakAuthMech(deployment, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+        final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deployment, userSessionManagement);
 
         UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deployment);
 
@@ -102,4 +102,9 @@ public class KeycloakServletExtension implements ServletExtension {
         cookieConfig.setPath(deploymentInfo.getContextPath());
         deploymentInfo.setServletSessionConfig(cookieConfig);
     }
+
+    protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, KeycloakDeployment deployment, UndertowUserSessionManagement userSessionManagement) {
+       log.info("creating ServletKeycloakAuthMech");
+       return new ServletKeycloakAuthMech(deployment, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+    }
 }
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
index 310958a..be72184 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
@@ -3,6 +3,7 @@ package org.keycloak.adapters.undertow;
 import io.undertow.security.idm.Account;
 import org.jboss.logging.Logger;
 import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.KeycloakAccount;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
 import org.keycloak.representations.AccessToken;
@@ -16,7 +17,7 @@ import java.util.Set;
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
 */
-public class KeycloakUndertowAccount implements Account, Serializable {
+public class KeycloakUndertowAccount implements Account, Serializable, KeycloakAccount {
     protected static Logger log = Logger.getLogger(KeycloakUndertowAccount.class);
     protected RefreshableKeycloakSecurityContext session;
     protected KeycloakPrincipal principal;
@@ -25,19 +26,27 @@ public class KeycloakUndertowAccount implements Account, Serializable {
     public KeycloakUndertowAccount(KeycloakPrincipal principal, RefreshableKeycloakSecurityContext session, KeycloakDeployment deployment) {
         this.principal = principal;
         this.session = session;
-        setRoles(session.getToken(), deployment);
+        setRoles(session.getToken());
     }
 
-    protected void setRoles(AccessToken accessToken, KeycloakDeployment deployment) {
+    protected void setRoles(AccessToken accessToken) {
         Set<String> roles = null;
-        if (deployment.isUseResourceRoleMappings()) {
-            AccessToken.Access access = accessToken.getResourceAccess(deployment.getResourceName());
+        if (session.getDeployment().isUseResourceRoleMappings()) {
+            log.info("useResourceRoleMappings");
+            AccessToken.Access access = accessToken.getResourceAccess(session.getDeployment().getResourceName());
             if (access != null) roles = access.getRoles();
         } else {
+            log.info("use realm role mappings");
             AccessToken.Access access = accessToken.getRealmAccess();
             if (access != null) roles = access.getRoles();
         }
         if (roles == null) roles = Collections.emptySet();
+        /*
+        log.info("Setting roles: ");
+        for (String role : roles) {
+            log.info("   role: " + role);
+        }
+        */
         this.accountRoles = roles;
     }
 
@@ -51,22 +60,17 @@ public class KeycloakUndertowAccount implements Account, Serializable {
         return accountRoles;
     }
 
-    public AccessToken getAccessToken() {
-        return session.getToken();
-    }
-
-    public String getEncodedAccessToken() {
-        return session.getTokenString();
-    }
-
+    @Override
     public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
         return session;
     }
 
-    public boolean isActive(KeycloakDeployment deployment) {
-        // this object may have been serialized, so we need to reset realm config/metadata
+    public void setDeployment(KeycloakDeployment deployment) {
         session.setDeployment(deployment);
-        log.info("realmConfig notBefore: " + deployment.getNotBefore());
+    }
+
+    public boolean isActive() {
+        // this object may have been serialized, so we need to reset realm config/metadata
         if (session.isActive()) {
             log.info("session is active");
             return true;
@@ -81,7 +85,7 @@ public class KeycloakUndertowAccount implements Account, Serializable {
         }
         log.info("refresh succeeded");
 
-        setRoles(session.getToken(), deployment);
+        setRoles(session.getToken());
         return true;
     }
 
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
index 2ce8f06..42b9237 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
@@ -29,8 +29,7 @@ public class ServletKeycloakAuthMech implements AuthenticationMechanism {
     @Override
     public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
         UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        ServletRequestAuthenticator authenticator = new ServletRequestAuthenticator(facade, deployment,
-                portManager.getConfidentialPort(exchange), securityContext, exchange, userSessionManagement);
+        ServletRequestAuthenticator authenticator = createRequestAuthenticator(exchange, securityContext, facade);
         AuthOutcome outcome = authenticator.authenticate();
         if (outcome == AuthOutcome.AUTHENTICATED) {
             return AuthenticationMechanismOutcome.AUTHENTICATED;
@@ -46,6 +45,11 @@ public class ServletKeycloakAuthMech implements AuthenticationMechanism {
         return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
     }
 
+    protected ServletRequestAuthenticator createRequestAuthenticator(HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
+        return new ServletRequestAuthenticator(facade, deployment,
+                portManager.getConfidentialPort(exchange), securityContext, exchange, userSessionManagement);
+    }
+
     @Override
     public ChallengeResult sendChallenge(HttpServerExchange exchange, SecurityContext securityContext) {
         AuthChallenge challenge = exchange.getAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY);
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
index f294eb7..f9c2edf 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
@@ -5,6 +5,7 @@ import io.undertow.server.HttpServerExchange;
 import io.undertow.servlet.handlers.ServletRequestContext;
 import org.keycloak.KeycloakSecurityContext;
 import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakAccount;
 import org.keycloak.adapters.KeycloakDeployment;
 
 import javax.servlet.http.HttpServletRequest;
@@ -39,7 +40,8 @@ public class ServletRequestAuthenticator extends UndertowRequestAuthenticator {
             log.info("Account was not in session, returning null");
             return false;
         }
-        if (account.isActive(deployment)) {
+        account.setDeployment(deployment);
+        if (account.isActive()) {
             log.info("Cached account found");
             securityContext.authenticationComplete(account, "KEYCLOAK", false);
             propagateKeycloakContext( account);
@@ -59,7 +61,7 @@ public class ServletRequestAuthenticator extends UndertowRequestAuthenticator {
     }
 
     @Override
-    protected void login(KeycloakUndertowAccount account) {
+    protected void login(KeycloakAccount account) {
         final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
         HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
         HttpSession session = req.getSession(true);
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
index 89b2e11..cd5fdaa 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
@@ -4,6 +4,7 @@ import io.undertow.security.api.SecurityContext;
 import io.undertow.server.HttpServerExchange;
 import org.keycloak.KeycloakPrincipal;
 import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakAccount;
 import org.keycloak.adapters.KeycloakDeployment;
 import org.keycloak.adapters.OAuthRequestAuthenticator;
 import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
@@ -46,7 +47,7 @@ public class UndertowRequestAuthenticator extends RequestAuthenticator {
         login(account);
     }
 
-    protected void login(KeycloakUndertowAccount account) {
+    protected void login(KeycloakAccount account) {
 
     }
 
diff --git a/integration/wildfly-adapter/pom.xml b/integration/wildfly-adapter/pom.xml
new file mode 100755
index 0000000..7ed0602
--- /dev/null
+++ b/integration/wildfly-adapter/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.0-alpha-3-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-wildfly-adapter</artifactId>
+    <name>Keycloak Wildfly Integration</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>3.1.2.GA</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-undertow-adapter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jboss-adapter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${keycloak.apache.httpcomponents.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.picketbox</groupId>
+            <artifactId>picketbox</artifactId>
+            <version>4.0.20.Final</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/SecurityInfoHelper.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/SecurityInfoHelper.java
new file mode 100755
index 0000000..9838772
--- /dev/null
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/SecurityInfoHelper.java
@@ -0,0 +1,116 @@
+package org.keycloak.adapters.wildfly;
+
+import org.jboss.security.NestableGroup;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.keycloak.adapters.KeycloakAccount;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SecurityInfoHelper {
+    public static void propagateSessionInfo(KeycloakAccount account) {
+        Subject subject = new Subject();
+        Set<Principal> principals = subject.getPrincipals();
+        principals.add(account.getPrincipal());
+        Group[] roleSets = getRoleSets(account.getRoles());
+        for (int g = 0; g < roleSets.length; g++) {
+            Group group = roleSets[g];
+            String name = group.getName();
+            Group subjectGroup = createGroup(name, principals);
+            if (subjectGroup instanceof NestableGroup) {
+                /* A NestableGroup only allows Groups to be added to it so we
+                need to add a SimpleGroup to subjectRoles to contain the roles
+                */
+                SimpleGroup tmp = new SimpleGroup("Roles");
+                subjectGroup.addMember(tmp);
+                subjectGroup = tmp;
+            }
+            // Copy the group members to the Subject group
+            Enumeration<? extends Principal> members = group.members();
+            while (members.hasMoreElements()) {
+                Principal role = (Principal) members.nextElement();
+                subjectGroup.addMember(role);
+            }
+        }
+        // add the CallerPrincipal group if none has been added in getRoleSets
+        Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
+        callerGroup.addMember(account.getPrincipal());
+        principals.add(callerGroup);
+        org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+        Principal userPrincipal = getPrincipal(subject);
+        sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
+    }
+
+    /**
+     * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
+     * considered or the single subject inside the CallerPrincipal group.
+     *
+     * @param subject
+     * @return the authenticated subject
+     */
+    protected static Principal getPrincipal(Subject subject) {
+        Principal principal = null;
+        Principal callerPrincipal = null;
+        if (subject != null) {
+            Set<Principal> principals = subject.getPrincipals();
+            if (principals != null && !principals.isEmpty()) {
+                for (Principal p : principals) {
+                    if (!(p instanceof Group) && principal == null) {
+                        principal = p;
+                    }
+                    if (p instanceof Group) {
+                        Group g = Group.class.cast(p);
+                        if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
+                            Enumeration<? extends Principal> e = g.members();
+                            if (e.hasMoreElements())
+                                callerPrincipal = e.nextElement();
+                        }
+                    }
+                }
+            }
+        }
+        return callerPrincipal == null ? principal : callerPrincipal;
+    }
+
+    protected static Group createGroup(String name, Set<Principal> principals) {
+        Group roles = null;
+        Iterator<Principal> iter = principals.iterator();
+        while (iter.hasNext()) {
+            Object next = iter.next();
+            if ((next instanceof Group) == false)
+                continue;
+            Group grp = (Group) next;
+            if (grp.getName().equals(name)) {
+                roles = grp;
+                break;
+            }
+        }
+        // If we did not find a group create one
+        if (roles == null) {
+            roles = new SimpleGroup(name);
+            principals.add(roles);
+        }
+        return roles;
+    }
+
+    protected static Group[] getRoleSets(Collection<String> roleSet) {
+        SimpleGroup roles = new SimpleGroup("Roles");
+        Group[] roleSets = {roles};
+        for (String role : roleSet) {
+            roles.addMember(new SimplePrincipal(role));
+        }
+        return roleSets;
+    }
+}
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
new file mode 100755
index 0000000..99c411c
--- /dev/null
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
@@ -0,0 +1,29 @@
+package org.keycloak.adapters.wildfly;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.servlet.api.ConfidentialPortManager;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
+import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
+import org.keycloak.adapters.undertow.UndertowHttpFacade;
+import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class WildflyAuthenticationMechanism extends ServletKeycloakAuthMech {
+
+    public WildflyAuthenticationMechanism(KeycloakDeployment deployment,
+                                          UndertowUserSessionManagement userSessionManagement,
+                                          ConfidentialPortManager portManager) {
+        super(deployment, userSessionManagement, portManager);
+    }
+
+    @Override
+    protected ServletRequestAuthenticator createRequestAuthenticator(HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
+        return new WildflyRequestAuthenticator(facade, deployment,
+                portManager.getConfidentialPort(exchange), securityContext, exchange, userSessionManagement);
+    }
+}
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
new file mode 100755
index 0000000..e0623ad
--- /dev/null
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
@@ -0,0 +1,24 @@
+package org.keycloak.adapters.wildfly;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.undertow.KeycloakServletExtension;
+import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
+import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class WildflyKeycloakServletExtension extends KeycloakServletExtension {
+    protected static Logger log = Logger.getLogger(WildflyKeycloakServletExtension.class);
+
+    @Override
+    protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, KeycloakDeployment deployment,
+                                                                    UndertowUserSessionManagement userSessionManagement) {
+        log.info("creating WildflyAuthenticationMechanism");
+        return new WildflyAuthenticationMechanism(deployment, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+
+    }
+}
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyRequestAuthenticator.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyRequestAuthenticator.java
new file mode 100755
index 0000000..0b3563a
--- /dev/null
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyRequestAuthenticator.java
@@ -0,0 +1,136 @@
+package org.keycloak.adapters.wildfly;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import org.jboss.logging.Logger;
+import org.jboss.security.NestableGroup;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
+import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
+import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
+    protected static Logger log = Logger.getLogger(WildflyRequestAuthenticator.class);
+
+    public WildflyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
+                                       SecurityContext securityContext, HttpServerExchange exchange,
+                                       UndertowUserSessionManagement userSessionManagement) {
+        super(facade, deployment, sslRedirectPort, securityContext, exchange, userSessionManagement);
+    }
+
+    @Override
+    protected void propagateKeycloakContext(KeycloakUndertowAccount account) {
+        super.propagateKeycloakContext(account);
+        SecurityInfoHelper.propagateSessionInfo(account);
+        log.info("propagate security context to wildfly");
+        Subject subject = new Subject();
+        Set<Principal> principals = subject.getPrincipals();
+        principals.add(account.getPrincipal());
+        Group[] roleSets = getRoleSets(account.getRoles());
+        for (int g = 0; g < roleSets.length; g++) {
+            Group group = roleSets[g];
+            String name = group.getName();
+            Group subjectGroup = createGroup(name, principals);
+            if (subjectGroup instanceof NestableGroup) {
+                /* A NestableGroup only allows Groups to be added to it so we
+                need to add a SimpleGroup to subjectRoles to contain the roles
+                */
+                SimpleGroup tmp = new SimpleGroup("Roles");
+                subjectGroup.addMember(tmp);
+                subjectGroup = tmp;
+            }
+            // Copy the group members to the Subject group
+            Enumeration<? extends Principal> members = group.members();
+            while (members.hasMoreElements()) {
+                Principal role = (Principal) members.nextElement();
+                subjectGroup.addMember(role);
+            }
+        }
+        // add the CallerPrincipal group if none has been added in getRoleSets
+        Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
+        callerGroup.addMember(account.getPrincipal());
+        principals.add(callerGroup);
+        org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+        Principal userPrincipal = getPrincipal(subject);
+        sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
+    }
+
+    /**
+     * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
+     * considered or the single subject inside the CallerPrincipal group.
+     *
+     * @param subject
+     * @return the authenticated subject
+     */
+    protected Principal getPrincipal(Subject subject) {
+        Principal principal = null;
+        Principal callerPrincipal = null;
+        if (subject != null) {
+            Set<Principal> principals = subject.getPrincipals();
+            if (principals != null && !principals.isEmpty()) {
+                for (Principal p : principals) {
+                    if (!(p instanceof Group) && principal == null) {
+                        principal = p;
+                    }
+                    if (p instanceof Group) {
+                        Group g = Group.class.cast(p);
+                        if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
+                            Enumeration<? extends Principal> e = g.members();
+                            if (e.hasMoreElements())
+                                callerPrincipal = e.nextElement();
+                        }
+                    }
+                }
+            }
+        }
+        return callerPrincipal == null ? principal : callerPrincipal;
+    }
+
+    protected Group createGroup(String name, Set<Principal> principals) {
+        Group roles = null;
+        Iterator<Principal> iter = principals.iterator();
+        while (iter.hasNext()) {
+            Object next = iter.next();
+            if ((next instanceof Group) == false)
+                continue;
+            Group grp = (Group) next;
+            if (grp.getName().equals(name)) {
+                roles = grp;
+                break;
+            }
+        }
+        // If we did not find a group create one
+        if (roles == null) {
+            roles = new SimpleGroup(name);
+            principals.add(roles);
+        }
+        return roles;
+    }
+
+    protected Group[] getRoleSets(Collection<String> roleSet) {
+        SimpleGroup roles = new SimpleGroup("Roles");
+        Group[] roleSets = {roles};
+        for (String role : roleSet) {
+            roles.addMember(new SimplePrincipal(role));
+        }
+        return roleSets;
+    }
+
+}
diff --git a/integration/wildfly-adapter/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension b/integration/wildfly-adapter/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension
new file mode 100755
index 0000000..a46a78e
--- /dev/null
+++ b/integration/wildfly-adapter/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension
@@ -0,0 +1 @@
+org.keycloak.adapters.wildfly.WildflyKeycloakServletExtension
diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
index 59fd9aa..16872c8 100755
--- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
+++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
@@ -48,11 +48,30 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
     // Seems wise to have this run after INSTALL_WAR_DEPLOYMENT
     public static final int PRIORITY = Phase.INSTALL_WAR_DEPLOYMENT - 1;
 
+    // not sure if we need this yet, keeping here just in case
+    protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
+        String deploymentName = deploymentUnit.getName();
+        if (!service.isKeycloakDeployment(deploymentName)) {
+            return;
+        }
+        WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+        if (warMetaData == null) return;
+        JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+        if (webMetaData == null) return;
+
+        LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+        if (loginConfig == null || !loginConfig.getAuthMethod().equalsIgnoreCase("KEYCLOAK")) {
+            return;
+        }
+
+        webMetaData.setSecurityDomain("keycloak");
+    }
+
     @Override
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
-        String deploymentName = deploymentUnit.getName();
 
+        String deploymentName = deploymentUnit.getName();
         KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
         //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName);
         if (service.isKeycloakDeployment(deploymentName)) {
@@ -61,6 +80,9 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
         }
 
         // FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
+
+        // todo notsure if we need this
+        // addSecurityDomain(deploymentUnit, service);
     }
 
     private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, String deploymentName, KeycloakAdapterConfigService service) {
diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
index d16645d..5dd1e52 100755
--- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
+++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakDependencyProcessor.java
@@ -36,7 +36,9 @@ import org.keycloak.subsystem.logging.KeycloakLogger;
  */
 public class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
 
+    private static final ModuleIdentifier KEYCLOAK_WILDFLY_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-adapter");
     private static final ModuleIdentifier KEYCLOAK_UNDERTOW_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-undertow-adapter");
+    private static final ModuleIdentifier KEYCLOAK_JBOSS_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-jboss-adapter-core");
     private static final ModuleIdentifier KEYCLOAK_CORE_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-adapter-core");
     private static final ModuleIdentifier KEYCLOAK_CORE = ModuleIdentifier.create("org.keycloak.keycloak-core");
     //private static final ModuleIdentifier APACHE_HTTPCOMPONENTS = ModuleIdentifier.create("org.apache.httpcomponents");
@@ -51,7 +53,9 @@ public class KeycloakDependencyProcessor implements DeploymentUnitProcessor {
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
 
-        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_UNDERTOW_ADAPTER, false, false, true, false));
+        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_WILDFLY_ADAPTER, false, false, true, false));
+        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_UNDERTOW_ADAPTER, false, false, false, false));
+        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_JBOSS_CORE_ADAPTER, false, false, false, false));
         moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE_ADAPTER, false, false, false, false));
         moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE, false, false, false, false));
         //moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, APACHE_HTTPCOMPONENTS, false, false, true, false));
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index c5cc177..50ed5ea 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -218,7 +218,7 @@ public class AdminService {
         }
     }
 
-        @Path("isLoggedIn.js")
+    @Path("isLoggedIn.js")
     @GET
     @Produces("application/javascript")
     @NoCache