keycloak-aplcache

Changes

pom.xml 22(+22 -0)

Details

diff --git a/adapters/oidc/pom.xml b/adapters/oidc/pom.xml
index 91a99a5..ef9e79e 100755
--- a/adapters/oidc/pom.xml
+++ b/adapters/oidc/pom.xml
@@ -45,5 +45,6 @@
         <module>tomcat</module>
         <module>undertow</module>
         <module>wildfly</module>
+        <module>wildfly-elytron</module>
     </modules>
 </project>
diff --git a/adapters/oidc/wildfly/wildfly-adapter/pom.xml b/adapters/oidc/wildfly/wildfly-adapter/pom.xml
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/SecurityInfoHelper.java b/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/SecurityInfoHelper.java
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java b/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java b/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyRequestAuthenticator.java b/adapters/oidc/wildfly/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyRequestAuthenticator.java
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly/wildfly-adapter/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension b/adapters/oidc/wildfly/wildfly-adapter/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension
old mode 100755
new mode 100644
diff --git a/adapters/oidc/wildfly-elytron/pom.xml b/adapters/oidc/wildfly-elytron/pom.xml
new file mode 100755
index 0000000..5aefb70
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2016 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>3.1.0.CR1-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
+    <name>Keycloak Wildfly Elytron OIDC Adapter</name>
+    <description/>
+
+    <properties>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.wildfly.common</groupId>
+            <artifactId>wildfly-common</artifactId>
+            <version>1.2.0.Beta1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly.security</groupId>
+            <artifactId>wildfly-elytron</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly.security.elytron-web</groupId>
+            <artifactId>undertow-server</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronAccount.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronAccount.java
new file mode 100644
index 0000000..c8db009
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronAccount.java
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OidcKeycloakAccount;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.wildfly.security.auth.server.SecurityIdentity;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronAccount implements OidcKeycloakAccount {
+
+    protected static Logger log = Logger.getLogger(ElytronAccount.class);
+
+    private final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
+
+    public ElytronAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        this.principal = principal;
+    }
+
+    @Override
+    public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
+        return principal.getKeycloakSecurityContext();
+    }
+
+    @Override
+    public Principal getPrincipal() {
+        return principal;
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        Set<String> roles = new HashSet<>();
+
+        return roles;
+    }
+
+    void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+        principal.getKeycloakSecurityContext().setCurrentRequestInfo(deployment, tokenStore);
+    }
+
+    public boolean checkActive() {
+        RefreshableKeycloakSecurityContext session = getKeycloakSecurityContext();
+
+        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) {
+            log.debug("session is active");
+            return true;
+        }
+
+        log.debug("session not active");
+
+        return false;
+    }
+
+    boolean tryRefresh(CallbackHandler callbackHandler) {
+        log.debug("Trying to refresh");
+
+        RefreshableKeycloakSecurityContext securityContext = getKeycloakSecurityContext();
+
+        if (securityContext == null) {
+            log.debug("No security context. Aborting refresh.");
+        }
+
+        if (securityContext.refreshExpiredToken(false)) {
+            SecurityIdentity securityIdentity = SecurityIdentityUtil.authorize(callbackHandler, principal);
+
+            if (securityIdentity != null) {
+                log.debug("refresh succeeded");
+                return true;
+            }
+
+            return false;
+        }
+
+        return checkActive();
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronCookieTokenStore.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronCookieTokenStore.java
new file mode 100644
index 0000000..eda7d17
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronCookieTokenStore.java
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import java.security.Principal;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.CookieTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OidcKeycloakAccount;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.Scope;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronCookieTokenStore implements ElytronTokeStore {
+
+    protected static Logger log = Logger.getLogger(ElytronCookieTokenStore.class);
+
+    private final ElytronHttpFacade httpFacade;
+    private final CallbackHandler callbackHandler;
+
+    public ElytronCookieTokenStore(ElytronHttpFacade httpFacade, CallbackHandler callbackHandler) {
+        this.httpFacade = httpFacade;
+        this.callbackHandler = callbackHandler;
+    }
+
+    @Override
+    public void checkCurrentToken() {
+        KeycloakDeployment deployment = httpFacade.getDeployment();
+        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(deployment, httpFacade, this);
+
+        if (principal == null) {
+            return;
+        }
+
+        RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
+
+        if (securityContext.isActive() && !securityContext.getDeployment().isAlwaysRefreshToken()) return;
+
+        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
+        // not be updated
+        boolean success = securityContext.refreshExpiredToken(false);
+        if (success && securityContext.isActive()) return;
+
+        saveAccountInfo(new ElytronAccount(principal));
+    }
+
+    @Override
+    public boolean isCached(RequestAuthenticator authenticator) {
+        KeycloakDeployment deployment = httpFacade.getDeployment();
+        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(deployment, httpFacade, this);
+        if (principal == null) {
+            log.debug("Account was not in cookie or was invalid, returning null");
+            return false;
+        }
+        ElytronAccount account = new ElytronAccount(principal);
+
+        if (!deployment.getRealm().equals(account.getKeycloakSecurityContext().getRealm())) {
+            log.debug("Account in session belongs to a different realm than for this request.");
+            return false;
+        }
+
+        boolean active = account.checkActive();
+
+        if (!active) {
+            active = account.tryRefresh(this.callbackHandler);
+        }
+
+        if (active) {
+            log.debug("Cached account found");
+            restoreRequest();
+            httpFacade.authenticationComplete(account, true);
+            return true;
+        } else {
+            log.debug("Account was not active, removing cookie and returning false");
+            CookieTokenStore.removeCookie(httpFacade);
+            return false;
+        }
+    }
+
+    @Override
+    public void saveAccountInfo(OidcKeycloakAccount account) {
+        RefreshableKeycloakSecurityContext secContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
+        CookieTokenStore.setTokenCookie(this.httpFacade.getDeployment(), this.httpFacade, secContext);
+        HttpScope exchange = this.httpFacade.getScope(Scope.EXCHANGE);
+
+        exchange.registerForNotification(httpServerScopes -> logout());
+
+        exchange.setAttachment(ElytronAccount.class.getName(), account);
+        exchange.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
+
+        restoreRequest();
+    }
+
+    @Override
+    public void logout() {
+        logout(false);
+    }
+
+    @Override
+    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
+        CookieTokenStore.setTokenCookie(this.httpFacade.getDeployment(), httpFacade, securityContext);
+    }
+
+    @Override
+    public void saveRequest() {
+
+    }
+
+    @Override
+    public boolean restoreRequest() {
+        return false;
+    }
+
+    @Override
+    public void logout(boolean glo) {
+        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(this.httpFacade.getDeployment(), this.httpFacade, this);
+
+        if (principal == null) {
+            return;
+        }
+
+        CookieTokenStore.removeCookie(this.httpFacade);
+
+        if (glo) {
+            KeycloakSecurityContext ksc = (KeycloakSecurityContext) principal.getKeycloakSecurityContext();
+
+            if (ksc == null) {
+                return;
+            }
+
+            KeycloakDeployment deployment = httpFacade.getDeployment();
+
+            if (!deployment.isBearerOnly() && ksc != null && ksc instanceof RefreshableKeycloakSecurityContext) {
+                ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
+            }
+        }
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java
new file mode 100644
index 0000000..bc2e903
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java
@@ -0,0 +1,394 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import org.bouncycastle.asn1.cmp.Challenge;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OIDCHttpFacade;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.spi.AuthChallenge;
+import org.keycloak.adapters.spi.AuthenticationError;
+import org.keycloak.adapters.spi.LogoutError;
+import org.keycloak.enums.TokenStore;
+import org.wildfly.security.auth.server.SecurityIdentity;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.HttpServerCookie;
+import org.wildfly.security.http.HttpServerMechanismsResponder;
+import org.wildfly.security.http.HttpServerRequest;
+import org.wildfly.security.http.HttpServerResponse;
+import org.wildfly.security.http.Scope;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.cert.X509Certificate;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+class ElytronHttpFacade implements OIDCHttpFacade {
+
+    private final HttpServerRequest request;
+    private final CallbackHandler callbackHandler;
+    private final AdapterTokenStore tokenStore;
+    private final AdapterDeploymentContext deploymentContext;
+    private Consumer<HttpServerResponse> responseConsumer;
+    private ElytronAccount account;
+    private SecurityIdentity securityIdentity;
+    private boolean restored;
+
+    public ElytronHttpFacade(HttpServerRequest request, AdapterDeploymentContext deploymentContext, CallbackHandler handler) {
+        this.request = request;
+        this.deploymentContext = deploymentContext;
+        this.callbackHandler = handler;
+        this.tokenStore = createTokenStore();
+        this.responseConsumer = response -> {};
+    }
+
+    void authenticationComplete(ElytronAccount account, boolean storeToken) {
+        this.securityIdentity = SecurityIdentityUtil.authorize(this.callbackHandler, account.getPrincipal());
+
+        if (securityIdentity != null) {
+            this.account = account;
+            RefreshableKeycloakSecurityContext keycloakSecurityContext = account.getKeycloakSecurityContext();
+            account.setCurrentRequestInfo(keycloakSecurityContext.getDeployment(), this.tokenStore);
+            if (storeToken) {
+                this.tokenStore.saveAccountInfo(account);
+            }
+        }
+    }
+
+    void authenticationComplete() {
+        if (securityIdentity != null) {
+            this.request.authenticationComplete(response -> {
+                if (!restored) {
+                    responseConsumer.accept(response);
+                }
+            }, () -> ((ElytronTokeStore) tokenStore).logout(true));
+        }
+    }
+
+    void authenticationFailed() {
+        this.request.authenticationFailed("Authentication Failed", response -> responseConsumer.accept(response));
+    }
+
+    void noAuthenticationInProgress() {
+        this.request.noAuthenticationInProgress();
+    }
+
+    void noAuthenticationInProgress(AuthChallenge challenge) {
+        if (challenge != null) {
+            challenge.challenge(this);
+        }
+        this.request.noAuthenticationInProgress(response -> responseConsumer.accept(response));
+    }
+
+    void authenticationInProgress() {
+        this.request.authenticationInProgress(response -> responseConsumer.accept(response));
+    }
+
+    HttpScope getScope(Scope scope) {
+        return request.getScope(scope);
+    }
+
+    HttpScope getScope(Scope scope, String id) {
+        return request.getScope(scope, id);
+    }
+
+    Collection<String> getScopeIds(Scope scope) {
+        return request.getScopeIds(scope);
+    }
+
+    AdapterTokenStore getTokenStore() {
+        return this.tokenStore;
+    }
+
+    KeycloakDeployment getDeployment() {
+        return deploymentContext.resolveDeployment(this);
+    }
+
+    private AdapterTokenStore createTokenStore() {
+        KeycloakDeployment deployment = getDeployment();
+
+        if (TokenStore.SESSION.equals(deployment.getTokenStore())) {
+            return new ElytronSessionTokenStore(this, this.callbackHandler);
+        } else {
+            return new ElytronCookieTokenStore(this, this.callbackHandler);
+        }
+    }
+
+    @Override
+    public Request getRequest() {
+        return new Request() {
+            @Override
+            public String getMethod() {
+                return request.getRequestMethod();
+            }
+
+            @Override
+            public String getURI() {
+                try {
+                    return URLDecoder.decode(request.getRequestURI().toString(), "UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    throw new RuntimeException("Failed to decode request URI", e);
+                }
+            }
+
+            @Override
+            public String getRelativePath() {
+                return request.getRequestPath();
+            }
+
+            @Override
+            public boolean isSecure() {
+                return request.getRequestURI().getScheme().equals("https");
+            }
+
+            @Override
+            public String getFirstParam(String param) {
+                throw new RuntimeException("Not implemented.");
+            }
+
+            @Override
+            public String getQueryParamValue(String param) {
+                URI requestURI = request.getRequestURI();
+                String query = requestURI.getQuery();
+                if (query != null) {
+                    String[] parameters = query.split("&");
+                    for (String parameter : parameters) {
+                        String[] keyValue = parameter.split("=");
+                        if (keyValue[0].equals(param)) {
+                            return keyValue[1];
+                        }
+                    }
+                }
+                return null;
+            }
+
+            @Override
+            public Cookie getCookie(final String cookieName) {
+                List<HttpServerCookie> cookies = request.getCookies();
+
+                if (cookies != null) {
+                    for (HttpServerCookie cookie : cookies) {
+                        if (cookie.getName().equals(cookieName)) {
+                            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
+                        }
+                    }
+                }
+
+                return null;
+            }
+
+            @Override
+            public String getHeader(String name) {
+                return request.getFirstRequestHeaderValue(name);
+            }
+
+            @Override
+            public List<String> getHeaders(String name) {
+                return request.getRequestHeaderValues(name);
+            }
+
+            @Override
+            public InputStream getInputStream() {
+                return request.getInputStream();
+            }
+
+            @Override
+            public String getRemoteAddr() {
+                InetSocketAddress sourceAddress = request.getSourceAddress();
+                if (sourceAddress == null) {
+                    return "";
+                }
+                InetAddress address = sourceAddress.getAddress();
+                if (address == null) {
+                    // this is unresolved, so we just return the host name not exactly spec, but if the name should be
+                    // resolved then a PeerNameResolvingHandler should be used and this is probably better than just
+                    // returning null
+                    return sourceAddress.getHostString();
+                }
+                return address.getHostAddress();
+            }
+
+            @Override
+            public void setError(AuthenticationError error) {
+                request.getScope(Scope.EXCHANGE).setAttachment(AuthenticationError.class.getName(), error);
+            }
+
+            @Override
+            public void setError(LogoutError error) {
+                request.getScope(Scope.EXCHANGE).setAttachment(LogoutError.class.getName(), error);
+            }
+        };
+    }
+
+    @Override
+    public Response getResponse() {
+        return new Response() {
+            @Override
+            public void setStatus(final int status) {
+                responseConsumer = responseConsumer.andThen(response -> response.setStatusCode(status));
+            }
+
+            @Override
+            public void addHeader(final String name, final String value) {
+                responseConsumer = responseConsumer.andThen(response -> response.addResponseHeader(name, value));
+            }
+
+            @Override
+            public void setHeader(String name, String value) {
+                addHeader(name, value);
+            }
+
+            @Override
+            public void resetCookie(final String name, final String path) {
+                responseConsumer = responseConsumer.andThen(response -> setCookie(name, "", path, null, 0, false, false, response));
+            }
+
+            @Override
+            public void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly) {
+                responseConsumer = responseConsumer.andThen(response -> setCookie(name, value, path, domain, maxAge, secure, httpOnly, response));
+            }
+
+            private void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly, HttpServerResponse response) {
+                response.setResponseCookie(new HttpServerCookie() {
+                    @Override
+                    public String getName() {
+                        return name;
+                    }
+
+                    @Override
+                    public String getValue() {
+                        return value;
+                    }
+
+                    @Override
+                    public String getDomain() {
+                        return domain;
+                    }
+
+                    @Override
+                    public int getMaxAge() {
+                        return maxAge;
+                    }
+
+                    @Override
+                    public String getPath() {
+                        return path;
+                    }
+
+                    @Override
+                    public boolean isSecure() {
+                        return secure;
+                    }
+
+                    @Override
+                    public int getVersion() {
+                        return 0;
+                    }
+
+                    @Override
+                    public boolean isHttpOnly() {
+                        return httpOnly;
+                    }
+                });
+            }
+
+            @Override
+            public OutputStream getOutputStream() {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                responseConsumer = responseConsumer.andThen(new Consumer<HttpServerResponse>() {
+                    @Override
+                    public void accept(HttpServerResponse httpServerResponse) {
+                        try {
+                            httpServerResponse.getOutputStream().write(stream.toByteArray());
+                        } catch (IOException e) {
+                            throw new RuntimeException("Failed to write to response output stream", e);
+                        }
+                    }
+                });
+                return stream;
+            }
+
+            @Override
+            public void sendError(int code) {
+                setStatus(code);
+            }
+
+            @Override
+            public void sendError(final int code, final String message) {
+                responseConsumer = responseConsumer.andThen(response -> {
+                    response.setStatusCode(code);
+                    response.addResponseHeader("Content-Type", "text/html");
+                    try {
+                        response.getOutputStream().write(message.getBytes());
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+            }
+
+            @Override
+            public void end() {
+
+            }
+        };
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain() {
+        return new X509Certificate[0];
+    }
+
+    @Override
+    public KeycloakSecurityContext getSecurityContext() {
+        if (account == null) {
+            return null;
+        }
+        return this.account.getKeycloakSecurityContext();
+    }
+
+    public boolean restoreRequest() {
+        restored = this.request.resumeRequest();
+        return restored;
+    }
+
+    public void suspendRequest() {
+        responseConsumer = responseConsumer.andThen(httpServerResponse -> request.suspendRequest());
+    }
+
+    public boolean isAuthorized() {
+        return this.securityIdentity != null;
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronRequestAuthenticator.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronRequestAuthenticator.java
new file mode 100644
index 0000000..643a716
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronRequestAuthenticator.java
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.BearerTokenRequestAuthenticator;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OAuthRequestAuthenticator;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.keycloak.adapters.spi.AuthOutcome;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.Scope;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronRequestAuthenticator extends RequestAuthenticator {
+
+    public ElytronRequestAuthenticator(CallbackHandler callbackHandler, ElytronHttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort) {
+        super(facade, deployment, facade.getTokenStore(), sslRedirectPort);
+    }
+
+    @Override
+    public AuthOutcome authenticate() {
+        AuthOutcome authenticate = super.authenticate();
+
+        if (AuthOutcome.AUTHENTICATED.equals(authenticate)) {
+            if (!getElytronHttpFacade().isAuthorized()) {
+                return AuthOutcome.FAILED;
+            }
+        }
+
+        return authenticate;
+    }
+
+    @Override
+    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
+        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
+    }
+
+    @Override
+    protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        getElytronHttpFacade().authenticationComplete(new ElytronAccount(principal), true);
+    }
+
+    @Override
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
+        getElytronHttpFacade().authenticationComplete(new ElytronAccount(principal), false);
+    }
+
+    @Override
+    protected String changeHttpSessionId(boolean create) {
+        HttpScope session = getElytronHttpFacade().getScope(Scope.SESSION);
+
+        if (create) {
+            if (!session.exists()) {
+                session.create();
+            }
+        }
+
+        return session != null ? session.getID() : null;
+    }
+
+    private ElytronHttpFacade getElytronHttpFacade() {
+        return (ElytronHttpFacade) facade;
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronSessionTokenStore.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronSessionTokenStore.java
new file mode 100644
index 0000000..385a8a6
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronSessionTokenStore.java
@@ -0,0 +1,202 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import java.util.function.Consumer;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OidcKeycloakAccount;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.HttpScopeNotification;
+import org.wildfly.security.http.Scope;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronSessionTokenStore implements ElytronTokeStore {
+
+    private static Logger log = Logger.getLogger(ElytronSessionTokenStore.class);
+
+    private final ElytronHttpFacade httpFacade;
+    private final CallbackHandler callbackHandler;
+
+    public ElytronSessionTokenStore(ElytronHttpFacade httpFacade, CallbackHandler callbackHandler) {
+        this.httpFacade = httpFacade;
+        this.callbackHandler = callbackHandler;
+    }
+
+    @Override
+    public void checkCurrentToken() {
+        HttpScope session = httpFacade.getScope(Scope.SESSION);
+        if (!session.exists()) return;
+        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
+        if (securityContext == null) return;
+
+        // just in case session got serialized
+        if (securityContext.getDeployment() == null) securityContext.setCurrentRequestInfo(httpFacade.getDeployment(), this);
+
+        if (securityContext.isActive() && !securityContext.getDeployment().isAlwaysRefreshToken()) return;
+
+        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
+        // not be updated
+        boolean success = securityContext.refreshExpiredToken(false);
+        if (success && securityContext.isActive()) return;
+
+        // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
+        session.setAttachment(KeycloakSecurityContext.class.getName(), null);
+        session.invalidate();
+    }
+
+    @Override
+    public boolean isCached(RequestAuthenticator authenticator) {
+        HttpScope session = this.httpFacade.getScope(Scope.SESSION);
+
+        if (session == null) {
+            log.debug("session was null, returning null");
+            return false;
+        }
+
+        ElytronAccount account;
+
+        try {
+            account = (ElytronAccount) session.getAttachment(ElytronAccount.class.getName());
+        } catch (IllegalStateException e) {
+            log.debug("session was invalidated.  Return false.");
+            return false;
+        }
+        if (account == null) {
+            log.debug("Account was not in session, returning null");
+            return false;
+        }
+
+        KeycloakDeployment deployment = httpFacade.getDeployment();
+
+        if (!deployment.getRealm().equals(account.getKeycloakSecurityContext().getRealm())) {
+            log.debug("Account in session belongs to a different realm than for this request.");
+            return false;
+        }
+
+        boolean active = account.checkActive();
+
+        if (!active) {
+            active = account.tryRefresh(this.callbackHandler);
+        }
+
+        if (active) {
+            log.debug("Cached account found");
+            restoreRequest();
+            httpFacade.authenticationComplete(account, true);
+            return true;
+        } else {
+            log.debug("Refresh failed. Account was not active. Returning null and invalidating Http session");
+            try {
+                session.setAttachment(KeycloakSecurityContext.class.getName(), null);
+                session.setAttachment(ElytronAccount.class.getName(), null);
+                session.invalidate();
+            } catch (Exception e) {
+                log.debug("Failed to invalidate session, might already be invalidated");
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public void saveAccountInfo(OidcKeycloakAccount account) {
+        HttpScope session = this.httpFacade.getScope(Scope.SESSION);
+
+        if (!session.exists()) {
+            session.create();
+        }
+
+        session.setAttachment(ElytronAccount.class.getName(), account);
+        session.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
+
+        session.registerForNotification(httpScopeNotification -> {
+            if (!httpScopeNotification.isOfType(HttpScopeNotification.SessionNotificationType.UNDEPLOY)) {
+                logout();
+            }
+        });
+
+        HttpScope scope = this.httpFacade.getScope(Scope.EXCHANGE);
+
+        scope.setAttachment(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
+    }
+
+    @Override
+    public void logout() {
+        logout(false);
+    }
+
+    @Override
+    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
+        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(this.httpFacade.getDeployment(), securityContext.getToken()), securityContext);
+        saveAccountInfo(new ElytronAccount(principal));
+    }
+
+    @Override
+    public void saveRequest() {
+        this.httpFacade.suspendRequest();
+    }
+
+    @Override
+    public boolean restoreRequest() {
+        return this.httpFacade.restoreRequest();
+    }
+
+    @Override
+    public void logout(boolean glo) {
+        HttpScope session = this.httpFacade.getScope(Scope.SESSION);
+
+        if (!session.exists()) {
+            return;
+        }
+
+        try {
+            if (glo) {
+                KeycloakSecurityContext ksc = (KeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
+
+                if (ksc == null) {
+                    return;
+                }
+
+                KeycloakDeployment deployment = httpFacade.getDeployment();
+
+                if (!deployment.isBearerOnly() && ksc != null && ksc instanceof RefreshableKeycloakSecurityContext) {
+                    ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
+                }
+            }
+
+            session.setAttachment(KeycloakSecurityContext.class.getName(), null);
+            session.setAttachment(ElytronAccount.class.getName(), null);
+            session.invalidate();
+        } catch (IllegalStateException ise) {
+            // Session may be already logged-out in case that app has adminUrl
+            log.debugf("Session %s logged-out already", session.getID());
+        }
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronTokeStore.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronTokeStore.java
new file mode 100644
index 0000000..dc1486e
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronTokeStore.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.elytron;
+
+import org.keycloak.adapters.AdapterTokenStore;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ElytronTokeStore extends AdapterTokenStore {
+    void logout(boolean glo);
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakConfigurationServletListener.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakConfigurationServletListener.java
new file mode 100644
index 0000000..ad8e9d5
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakConfigurationServletListener.java
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.constants.AdapterConstants;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+/**
+ * <p>A {@link ServletContextListener} that parses the keycloak adapter configuration and set the same configuration
+ * as a {@link ServletContext} attribute in order to provide to {@link KeycloakHttpServerAuthenticationMechanism} a way
+ * to obtain the configuration when processing requests.
+ *
+ * <p>This listener should be automatically registered to a deployment using the subsystem.
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakConfigurationServletListener implements ServletContextListener {
+    @Override
+    public void contextInitialized(ServletContextEvent sce) {
+        ServletContext servletContext = sce.getServletContext();
+        String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
+        KeycloakConfigResolver configResolver;
+        AdapterDeploymentContext deploymentContext;
+
+        if (configResolverClass != null) {
+            try {
+                configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new AdapterDeploymentContext(configResolver);
+            } catch (Exception ex) {
+                deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+            }
+        } else {
+            InputStream is = getConfigInputStream(servletContext);
+
+            KeycloakDeployment deployment;
+
+            if (is == null) {
+                deployment = new KeycloakDeployment();
+            } else {
+                deployment = KeycloakDeploymentBuilder.build(is);
+            }
+
+            deploymentContext = new AdapterDeploymentContext(deployment);
+        }
+
+        servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent sce) {
+
+    }
+
+    private InputStream getConfigInputStream(ServletContext servletContext) {
+        InputStream is = getJSONFromServletContext(servletContext);
+
+        if (is == null) {
+            String path = servletContext.getInitParameter("keycloak.config.file");
+
+            if (path == null) {
+                is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
+            } else {
+                try {
+                    is = new FileInputStream(path);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return is;
+    }
+
+    private InputStream getJSONFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+
+        if (json == null) {
+            return null;
+        }
+
+        return new ByteArrayInputStream(json.getBytes());
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanism.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanism.java
new file mode 100644
index 0000000..3fcf9bf
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanism.java
@@ -0,0 +1,168 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.PreAuthActionsHandler;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.keycloak.adapters.spi.AuthChallenge;
+import org.keycloak.adapters.spi.AuthOutcome;
+import org.keycloak.adapters.spi.UserSessionManagement;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.HttpServerAuthenticationMechanism;
+import org.wildfly.security.http.HttpServerRequest;
+import org.wildfly.security.http.Scope;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
+
+    static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
+    static final String NAME = "KEYCLOAK";
+
+    private final Map<String, ?> properties;
+    private final CallbackHandler callbackHandler;
+    private final AdapterDeploymentContext deploymentContext;
+
+    public KeycloakHttpServerAuthenticationMechanism(Map<String, ?> properties, CallbackHandler callbackHandler, AdapterDeploymentContext deploymentContext) {
+        this.properties = properties;
+        this.callbackHandler = callbackHandler;
+        this.deploymentContext = deploymentContext;
+    }
+
+    @Override
+    public String getMechanismName() {
+        return NAME;
+    }
+
+    @Override
+    public void evaluateRequest(HttpServerRequest request) throws HttpAuthenticationException {
+        LOGGER.debugf("Evaluating request for path [%s]", request.getRequestURI());
+        AdapterDeploymentContext deploymentContext = getDeploymentContext(request);
+
+        if (deploymentContext == null) {
+            LOGGER.debugf("Ignoring request for path [%s] from mechanism [%s]. No deployment context found.", request.getRequestURI());
+            request.noAuthenticationInProgress();
+            return;
+        }
+
+        ElytronHttpFacade httpFacade = new ElytronHttpFacade(request, deploymentContext, callbackHandler);
+        KeycloakDeployment deployment = httpFacade.getDeployment();
+
+        if (!deployment.isConfigured()) {
+            request.noAuthenticationInProgress();
+            return;
+        }
+
+        RequestAuthenticator authenticator = createRequestAuthenticator(request, httpFacade, deployment);
+
+        httpFacade.getTokenStore().checkCurrentToken();
+
+        if (preActions(httpFacade, deploymentContext)) {
+            LOGGER.debugf("Pre-actions has aborted the evaluation of [%s]", request.getRequestURI());
+            httpFacade.authenticationInProgress();
+            return;
+        }
+
+        AuthOutcome outcome = authenticator.authenticate();
+
+        if (AuthOutcome.AUTHENTICATED.equals(outcome)) {
+            if (new AuthenticatedActionsHandler(deployment, httpFacade).handledRequest()) {
+                httpFacade.authenticationInProgress();
+            } else {
+                httpFacade.authenticationComplete();
+            }
+            return;
+        }
+
+        AuthChallenge challenge = authenticator.getChallenge();
+
+        if (challenge != null) {
+            httpFacade.noAuthenticationInProgress(challenge);
+            return;
+        }
+
+        if (AuthOutcome.FAILED.equals(outcome)) {
+            httpFacade.getResponse().setStatus(403);
+            httpFacade.authenticationFailed();
+            return;
+        }
+
+        httpFacade.noAuthenticationInProgress();
+    }
+
+    private ElytronRequestAuthenticator createRequestAuthenticator(HttpServerRequest request, ElytronHttpFacade httpFacade, KeycloakDeployment deployment) {
+        return new ElytronRequestAuthenticator(this.callbackHandler, httpFacade, deployment, getConfidentialPort(request));
+    }
+
+    private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
+        if (this.deploymentContext == null) {
+            return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(AdapterDeploymentContext.class.getName());
+        }
+
+        return this.deploymentContext;
+    }
+
+    private boolean preActions(ElytronHttpFacade httpFacade, AdapterDeploymentContext deploymentContext) {
+        NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
+
+        nodesRegistrationManagement.tryRegister(httpFacade.getDeployment());
+
+        PreAuthActionsHandler preActions = new PreAuthActionsHandler(new UserSessionManagement() {
+            @Override
+            public void logoutAll() {
+                Collection<String> sessions = httpFacade.getScopeIds(Scope.SESSION);
+                logoutHttpSessions(new ArrayList<>(sessions));
+            }
+
+            @Override
+            public void logoutHttpSessions(List<String> ids) {
+                for (String id : ids) {
+                    HttpScope session = httpFacade.getScope(Scope.SESSION, id);
+
+                    if (session != null) {
+                        session.invalidate();
+                    }
+                }
+
+            }
+        }, deploymentContext, httpFacade);
+
+        return preActions.handleRequest();
+    }
+
+    // TODO: obtain confidential port from Elytron
+    private int getConfidentialPort(HttpServerRequest request) {
+        return 8443;
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java
new file mode 100644
index 0000000..eb6b333
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpServerAuthenticationMechanism;
+import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakHttpServerAuthenticationMechanismFactory implements HttpServerAuthenticationMechanismFactory {
+
+    private final AdapterDeploymentContext deploymentContext;
+
+    /**
+     * <p>Creates a new instance.
+     *
+     * <p>A default constructor is necessary in order to allow this factory to be loaded via {@link java.util.ServiceLoader}.
+     */
+    public KeycloakHttpServerAuthenticationMechanismFactory() {
+        this(null);
+    }
+
+    public KeycloakHttpServerAuthenticationMechanismFactory(AdapterDeploymentContext deploymentContext) {
+        this.deploymentContext = deploymentContext;
+    }
+
+    @Override
+    public String[] getMechanismNames(Map<String, ?> properties) {
+        return new String[] {KeycloakHttpServerAuthenticationMechanism.NAME};
+    }
+
+    @Override
+    public HttpServerAuthenticationMechanism createAuthenticationMechanism(String mechanismName, Map<String, ?> properties, CallbackHandler callbackHandler) throws HttpAuthenticationException {
+        Map<String, Object> mechanismProperties = new HashMap();
+
+        mechanismProperties.putAll(properties);
+
+        if (KeycloakHttpServerAuthenticationMechanism.NAME.equals(mechanismName)) {
+            return new KeycloakHttpServerAuthenticationMechanism(properties, callbackHandler, this.deploymentContext);
+        }
+
+        return null;
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java
new file mode 100644
index 0000000..6042ec8
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.elytron;
+
+import java.security.Principal;
+import java.util.Set;
+
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.authz.MapAttributes;
+import org.wildfly.security.authz.RoleDecoder;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.Evidence;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakSecurityRealm implements SecurityRealm {
+
+    @Override
+    public RealmIdentity getRealmIdentity(Principal principal) throws RealmUnavailableException {
+        if (principal instanceof KeycloakPrincipal) {
+            return createRealmIdentity((KeycloakPrincipal) principal);
+        }
+        return RealmIdentity.NON_EXISTENT;
+    }
+
+    private RealmIdentity createRealmIdentity(KeycloakPrincipal principal) {
+        return new RealmIdentity() {
+            @Override
+            public Principal getRealmIdentityPrincipal() {
+                return principal;
+            }
+
+            @Override
+            public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+                return SupportLevel.UNSUPPORTED;
+            }
+
+            @Override
+            public <C extends Credential> C getCredential(Class<C> credentialType) throws RealmUnavailableException {
+                return null;
+            }
+
+            @Override
+            public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+                return SupportLevel.SUPPORTED;
+            }
+
+            @Override
+            public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
+                return principal != null;
+            }
+
+            @Override
+            public boolean exists() throws RealmUnavailableException {
+                return principal != null;
+            }
+
+            @Override
+            public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+                RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) principal.getKeycloakSecurityContext();
+                Attributes attributes = new MapAttributes();
+                Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
+
+                attributes.addAll(RoleDecoder.KEY_ROLES, roles);
+
+                return AuthorizationIdentity.basicIdentity(attributes);
+            }
+        };
+    }
+
+    @Override
+    public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+        return SupportLevel.UNSUPPORTED;
+    }
+
+    @Override
+    public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+        return SupportLevel.POSSIBLY_SUPPORTED;
+    }
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/SecurityIdentityUtil.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/SecurityIdentityUtil.java
new file mode 100644
index 0000000..28f6eb9
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/SecurityIdentityUtil.java
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.elytron;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
+import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
+import org.wildfly.security.auth.callback.SecurityIdentityCallback;
+import org.wildfly.security.auth.server.SecurityIdentity;
+import org.wildfly.security.evidence.Evidence;
+import org.wildfly.security.http.HttpAuthenticationException;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+final class SecurityIdentityUtil {
+
+    static final SecurityIdentity authorize(CallbackHandler callbackHandler, Principal principal) {
+        try {
+            EvidenceVerifyCallback evidenceVerifyCallback = new EvidenceVerifyCallback(new Evidence() {
+                @Override
+                public Principal getPrincipal() {
+                    return principal;
+                }
+            });
+
+            callbackHandler.handle(new Callback[]{evidenceVerifyCallback});
+
+            if (evidenceVerifyCallback.isVerified()) {
+                AuthorizeCallback authorizeCallback = new AuthorizeCallback(null, null);
+
+                try {
+                    callbackHandler.handle(new Callback[] {authorizeCallback});
+
+                    authorizeCallback.isAuthorized();
+                } catch (Exception e) {
+                    throw new HttpAuthenticationException(e);
+                }
+
+                SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
+
+                callbackHandler.handle(new Callback[]{AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
+
+                SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
+
+                return securityIdentity;
+            }
+        } catch (UnsupportedCallbackException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return null;
+    }
+
+}
diff --git a/adapters/oidc/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory b/adapters/oidc/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory
new file mode 100644
index 0000000..96a0441
--- /dev/null
+++ b/adapters/oidc/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory
@@ -0,0 +1,19 @@
+#
+# JBoss, Home of Professional Open Source.
+# Copyright 2016 Red Hat, Inc., and individual contributors
+# as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory
\ No newline at end of file
diff --git a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
index cb9b4d9..550eeeb 100644
--- a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
+++ b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.adapters.saml.profile;
 
+import static org.keycloak.adapters.saml.SamlPrincipal.DEFAULT_ROLE_ATTRIBUTE_NAME;
+
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.saml.AbstractInitiateLogin;
 import org.keycloak.adapters.saml.OnSessionCreated;
@@ -422,6 +424,11 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
                 }
             }
         }
+
+        // roles should also be there as regular attributes
+        // this mainly required for elytron and its ABAC nature
+        attributes.put(DEFAULT_ROLE_ATTRIBUTE_NAME, new ArrayList<>(roles));
+
         if (deployment.getPrincipalNamePolicy() == SamlDeployment.PrincipalNamePolicy.FROM_ATTRIBUTE) {
             if (deployment.getPrincipalAttributeName() != null) {
                 String attribute = attributes.getFirst(deployment.getPrincipalAttributeName());
diff --git a/adapters/saml/core-public/src/main/java/org/keycloak/adapters/saml/SamlPrincipal.java b/adapters/saml/core-public/src/main/java/org/keycloak/adapters/saml/SamlPrincipal.java
index f9a1e77..280c3fe 100755
--- a/adapters/saml/core-public/src/main/java/org/keycloak/adapters/saml/SamlPrincipal.java
+++ b/adapters/saml/core-public/src/main/java/org/keycloak/adapters/saml/SamlPrincipal.java
@@ -24,6 +24,7 @@ import java.io.Serializable;
 import java.security.Principal;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -31,6 +32,9 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class SamlPrincipal implements Serializable, Principal {
+
+    public static final String DEFAULT_ROLE_ATTRIBUTE_NAME = "Roles";
+
     private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
     private MultivaluedHashMap<String, String> friendlyAttributes = new MultivaluedHashMap<>();
     private String name;
@@ -99,6 +103,15 @@ public class SamlPrincipal implements Serializable, Principal {
     }
 
     /**
+     * Convenience function that gets the attributes associated with this principal
+     *
+     * @return attributes associated with this principal
+     */
+    public Map<String, List<String>> getAttributes() {
+        return Collections.unmodifiableMap(attributes);
+    }
+
+    /**
      * Convenience function that gets Attribute value by attribute friendly name
      *
      * @param friendlyName
diff --git a/adapters/saml/pom.xml b/adapters/saml/pom.xml
index 614646d..7ca4c17 100755
--- a/adapters/saml/pom.xml
+++ b/adapters/saml/pom.xml
@@ -39,5 +39,6 @@
         <module>wildfly</module>
         <module>as7-eap6</module>
         <module>servlet-filter</module>
+        <module>wildfly-elytron</module>
     </modules>
 </project>
diff --git a/adapters/saml/wildfly-elytron/pom.xml b/adapters/saml/wildfly-elytron/pom.xml
new file mode 100755
index 0000000..51af380
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>3.1.0.CR1-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-saml-wildfly-elytron-adapter</artifactId>
+    <name>Keycloak WildFly Elytron SAML Adapter</name>
+    <description/>
+
+    <properties>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-spi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-common</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-adapter-api-public</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <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>org.wildfly.security</groupId>
+            <artifactId>wildfly-elytron</artifactId>
+        </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>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronHttpFacade.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronHttpFacade.java
new file mode 100644
index 0000000..88e96f8
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronHttpFacade.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.cert.X509Certificate;
+
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlDeploymentContext;
+import org.keycloak.adapters.saml.SamlSession;
+import org.keycloak.adapters.saml.SamlSessionStore;
+import org.keycloak.adapters.spi.AuthChallenge;
+import org.keycloak.adapters.spi.AuthenticationError;
+import org.keycloak.adapters.spi.HttpFacade;
+import org.keycloak.adapters.spi.LogoutError;
+import org.keycloak.adapters.spi.SessionIdMapper;
+import org.wildfly.security.auth.callback.AnonymousAuthorizationCallback;
+import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
+import org.wildfly.security.auth.callback.SecurityIdentityCallback;
+import org.wildfly.security.auth.server.SecurityIdentity;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.HttpServerCookie;
+import org.wildfly.security.http.HttpServerMechanismsResponder;
+import org.wildfly.security.http.HttpServerRequest;
+import org.wildfly.security.http.HttpServerResponse;
+import org.wildfly.security.http.Scope;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+class ElytronHttpFacade implements HttpFacade {
+
+    private final HttpServerRequest request;
+    private final CallbackHandler callbackHandler;
+    private final SamlDeploymentContext deploymentContext;
+    private final SamlSessionStore sessionStore;
+    private Consumer<HttpServerResponse> responseConsumer;
+    private SecurityIdentity securityIdentity;
+    private boolean restored;
+    private SamlSession samlSession;
+
+    public ElytronHttpFacade(HttpServerRequest request, SessionIdMapper idMapper, SamlDeploymentContext deploymentContext, CallbackHandler handler) {
+        this.request = request;
+        this.deploymentContext = deploymentContext;
+        this.callbackHandler = handler;
+        this.responseConsumer = response -> {};
+        this.sessionStore = createTokenStore(idMapper);
+    }
+
+    private SamlSessionStore createTokenStore(SessionIdMapper idMapper) {
+        return new ElytronSamlSessionStore(this, idMapper, getDeployment());
+    }
+
+    void authenticationComplete(SamlSession samlSession) {
+        this.samlSession = samlSession;
+    }
+
+    void authenticationComplete() {
+        this.securityIdentity = SecurityIdentityUtil.authorize(this.callbackHandler, samlSession.getPrincipal());
+        this.request.authenticationComplete(response -> {
+            if (!restored) {
+                responseConsumer.accept(response);
+            }
+        }, () -> ((ElytronTokeStore) sessionStore).logout(true));
+    }
+
+    void authenticationCompleteAnonymous() {
+        try {
+            AnonymousAuthorizationCallback anonymousAuthorizationCallback = new AnonymousAuthorizationCallback(null);
+
+            callbackHandler.handle(new Callback[]{anonymousAuthorizationCallback});
+
+            if (anonymousAuthorizationCallback.isAuthorized()) {
+                callbackHandler.handle(new Callback[]{AuthenticationCompleteCallback.SUCCEEDED, new SecurityIdentityCallback()});
+            }
+
+            request.authenticationComplete(response -> response.forward(getRequest().getRelativePath()));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected error processing callbacks during logout.", e);
+        }
+    }
+
+    void authenticationFailed() {
+        this.request.authenticationFailed("Authentication Failed", response -> responseConsumer.accept(response));
+    }
+
+    void noAuthenticationInProgress(AuthChallenge challenge) {
+        if (challenge != null) {
+            challenge.challenge(this);
+        }
+        this.request.noAuthenticationInProgress(response -> responseConsumer.accept(response));
+    }
+
+    void authenticationInProgress() {
+        this.request.authenticationInProgress(response -> responseConsumer.accept(response));
+    }
+
+    HttpScope getScope(Scope scope) {
+        return request.getScope(scope);
+    }
+
+    HttpScope getScope(Scope scope, String id) {
+        return request.getScope(scope, id);
+    }
+
+    Collection<String> getScopeIds(Scope scope) {
+        return request.getScopeIds(scope);
+    }
+
+    SamlDeployment getDeployment() {
+        return deploymentContext.resolveDeployment(this);
+    }
+
+    @Override
+    public Request getRequest() {
+        return new Request() {
+            @Override
+            public String getMethod() {
+                return request.getRequestMethod();
+            }
+
+            @Override
+            public String getURI() {
+                try {
+                    return URLDecoder.decode(request.getRequestURI().toString(), "UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    throw new RuntimeException("Failed to decode request URI", e);
+                }
+            }
+
+            @Override
+            public String getRelativePath() {
+                return request.getRequestPath();
+            }
+
+            @Override
+            public boolean isSecure() {
+                return request.getRequestURI().getScheme().equals("https");
+            }
+
+            @Override
+            public String getFirstParam(String param) {
+                return request.getFirstParameterValue(param);
+            }
+
+            @Override
+            public String getQueryParamValue(String param) {
+                return request.getFirstParameterValue(param);
+            }
+
+            @Override
+            public Cookie getCookie(final String cookieName) {
+                List<HttpServerCookie> cookies = request.getCookies();
+
+                if (cookies != null) {
+                    for (HttpServerCookie cookie : cookies) {
+                        if (cookie.getName().equals(cookieName)) {
+                            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
+                        }
+                    }
+                }
+
+                return null;
+            }
+
+            @Override
+            public String getHeader(String name) {
+                return request.getFirstRequestHeaderValue(name);
+            }
+
+            @Override
+            public List<String> getHeaders(String name) {
+                return request.getRequestHeaderValues(name);
+            }
+
+            @Override
+            public InputStream getInputStream() {
+                return request.getInputStream();
+            }
+
+            @Override
+            public String getRemoteAddr() {
+                InetSocketAddress sourceAddress = request.getSourceAddress();
+                if (sourceAddress == null) {
+                    return "";
+                }
+                InetAddress address = sourceAddress.getAddress();
+                if (address == null) {
+                    // this is unresolved, so we just return the host name not exactly spec, but if the name should be
+                    // resolved then a PeerNameResolvingHandler should be used and this is probably better than just
+                    // returning null
+                    return sourceAddress.getHostString();
+                }
+                return address.getHostAddress();
+            }
+
+            @Override
+            public void setError(AuthenticationError error) {
+                request.getScope(Scope.EXCHANGE).setAttachment(AuthenticationError.class.getName(), error);
+            }
+
+            @Override
+            public void setError(LogoutError error) {
+                request.getScope(Scope.EXCHANGE).setAttachment(LogoutError.class.getName(), error);
+            }
+        };
+    }
+
+    @Override
+    public Response getResponse() {
+        return new Response() {
+            @Override
+            public void setStatus(final int status) {
+                responseConsumer = responseConsumer.andThen(response -> response.setStatusCode(status));
+            }
+
+            @Override
+            public void addHeader(final String name, final String value) {
+                responseConsumer = responseConsumer.andThen(response -> response.addResponseHeader(name, value));
+            }
+
+            @Override
+            public void setHeader(String name, String value) {
+                addHeader(name, value);
+            }
+
+            @Override
+            public void resetCookie(final String name, final String path) {
+                responseConsumer = responseConsumer.andThen(response -> setCookie(name, "", path, null, 0, false, false, response));
+            }
+
+            @Override
+            public void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly) {
+                responseConsumer = responseConsumer.andThen(response -> setCookie(name, value, path, domain, maxAge, secure, httpOnly, response));
+            }
+
+            private void setCookie(final String name, final String value, final String path, final String domain, final int maxAge, final boolean secure, final boolean httpOnly, HttpServerResponse response) {
+                response.setResponseCookie(new HttpServerCookie() {
+                    @Override
+                    public String getName() {
+                        return name;
+                    }
+
+                    @Override
+                    public String getValue() {
+                        return value;
+                    }
+
+                    @Override
+                    public String getDomain() {
+                        return domain;
+                    }
+
+                    @Override
+                    public int getMaxAge() {
+                        return maxAge;
+                    }
+
+                    @Override
+                    public String getPath() {
+                        return path;
+                    }
+
+                    @Override
+                    public boolean isSecure() {
+                        return secure;
+                    }
+
+                    @Override
+                    public int getVersion() {
+                        return 0;
+                    }
+
+                    @Override
+                    public boolean isHttpOnly() {
+                        return httpOnly;
+                    }
+                });
+            }
+
+            @Override
+            public OutputStream getOutputStream() {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                responseConsumer = responseConsumer.andThen(new Consumer<HttpServerResponse>() {
+                    @Override
+                    public void accept(HttpServerResponse httpServerResponse) {
+                        try {
+                            httpServerResponse.getOutputStream().write(stream.toByteArray());
+                        } catch (IOException e) {
+                            throw new RuntimeException("Failed to write to response output stream", e);
+                        }
+                    }
+                });
+                return stream;
+            }
+
+            @Override
+            public void sendError(int code) {
+                setStatus(code);
+            }
+
+            @Override
+            public void sendError(final int code, final String message) {
+                responseConsumer = responseConsumer.andThen(response -> {
+                    response.setStatusCode(code);
+                    response.addResponseHeader("Content-Type", "text/html");
+                    try {
+                        response.getOutputStream().write(message.getBytes());
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+            }
+
+            @Override
+            public void end() {
+
+            }
+        };
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain() {
+        return new X509Certificate[0];
+    }
+
+    public boolean restoreRequest() {
+        restored = this.request.resumeRequest();
+        return restored;
+    }
+
+    public void suspendRequest() {
+        responseConsumer = responseConsumer.andThen(httpServerResponse -> request.suspendRequest());
+    }
+
+    public boolean isAuthorized() {
+        return this.securityIdentity != null;
+    }
+
+    public URI getURI() {
+        return request.getRequestURI();
+    }
+
+    public SamlSessionStore getSessionStore() {
+        return sessionStore;
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlAuthenticator.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlAuthenticator.java
new file mode 100644
index 0000000..29975ed
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlAuthenticator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.saml.elytron;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.keycloak.adapters.saml.SamlAuthenticator;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlSession;
+import org.keycloak.adapters.saml.SamlSessionStore;
+import org.keycloak.adapters.saml.profile.SamlAuthenticationHandler;
+import org.keycloak.adapters.saml.profile.webbrowsersso.BrowserHandler;
+import org.keycloak.adapters.spi.HttpFacade;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronSamlAuthenticator extends SamlAuthenticator {
+    private final CallbackHandler callbackHandler;
+    private final ElytronHttpFacade facade;
+
+    public ElytronSamlAuthenticator(ElytronHttpFacade facade, SamlDeployment samlDeployment, CallbackHandler callbackHandler) {
+        super(facade, samlDeployment, facade.getSessionStore());
+        this.callbackHandler = callbackHandler;
+        this.facade = facade;
+    }
+
+    @Override
+    protected void completeAuthentication(SamlSession samlSession) {
+        facade.authenticationComplete(samlSession);
+    }
+
+    @Override
+    protected SamlAuthenticationHandler createBrowserHandler(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
+        return new BrowserHandler(facade, deployment, sessionStore);
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlEndpoint.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlEndpoint.java
new file mode 100644
index 0000000..17997e5
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlEndpoint.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.saml.elytron;
+
+import org.keycloak.adapters.saml.SamlAuthenticator;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlSession;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ElytronSamlEndpoint extends SamlAuthenticator {
+
+    private final ElytronHttpFacade facade;
+
+    public ElytronSamlEndpoint(ElytronHttpFacade facade, SamlDeployment samlDeployment) {
+        super(facade, samlDeployment, facade.getSessionStore());
+        this.facade = facade;
+    }
+
+    @Override
+    protected void completeAuthentication(SamlSession samlSession) {
+        facade.authenticationComplete(samlSession);
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlSessionStore.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlSessionStore.java
new file mode 100644
index 0000000..2ce6292
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronSamlSessionStore.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlSession;
+import org.keycloak.adapters.saml.SamlSessionStore;
+import org.keycloak.adapters.saml.SamlUtil;
+import org.keycloak.adapters.spi.SessionIdMapper;
+import org.keycloak.common.util.KeycloakUriBuilder;
+import org.wildfly.security.http.HttpScope;
+import org.wildfly.security.http.Scope;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ElytronSamlSessionStore implements SamlSessionStore, ElytronTokeStore {
+    protected static Logger log = Logger.getLogger(SamlSessionStore.class);
+    public static final String SAML_REDIRECT_URI = "SAML_REDIRECT_URI";
+
+    private final SessionIdMapper idMapper;
+    protected final SamlDeployment deployment;
+    private final ElytronHttpFacade exchange;
+
+
+    public ElytronSamlSessionStore(ElytronHttpFacade exchange, SessionIdMapper idMapper, SamlDeployment deployment) {
+        this.exchange = exchange;
+        this.idMapper = idMapper;
+        this.deployment = deployment;
+    }
+
+    @Override
+    public void setCurrentAction(CurrentAction action) {
+        if (action == CurrentAction.NONE && !exchange.getScope(Scope.SESSION).exists()) return;
+        exchange.getScope(Scope.SESSION).setAttachment(CURRENT_ACTION, action);
+    }
+
+    @Override
+    public boolean isLoggingIn() {
+        HttpScope session = exchange.getScope(Scope.SESSION);
+        if (!session.exists()) return false;
+        CurrentAction action = (CurrentAction) session.getAttachment(CURRENT_ACTION);
+        return action == CurrentAction.LOGGING_IN;
+    }
+
+    @Override
+    public boolean isLoggingOut() {
+        HttpScope session = exchange.getScope(Scope.SESSION);
+        if (!session.exists()) return false;
+        CurrentAction action = (CurrentAction) session.getAttachment(CURRENT_ACTION);
+        return action == CurrentAction.LOGGING_OUT;
+    }
+
+    @Override
+    public void logoutAccount() {
+        HttpScope session = getSession(false);
+        if (session.exists()) {
+            SamlSession samlSession = (SamlSession)session.getAttachment(SamlSession.class.getName());
+            if (samlSession != null) {
+                if (samlSession.getSessionIndex() != null) {
+                    idMapper.removeSession(session.getID());
+                }
+                session.setAttachment(SamlSession.class.getName(), null);
+            }
+            session.setAttachment(SAML_REDIRECT_URI, null);
+        }
+    }
+
+    @Override
+    public void logoutByPrincipal(String principal) {
+        Set<String> sessions = idMapper.getUserSessions(principal);
+        if (sessions != null) {
+            List<String> ids = new LinkedList<>();
+            ids.addAll(sessions);
+            logoutSessionIds(ids);
+            for (String id : ids) {
+                idMapper.removeSession(id);
+            }
+        }
+
+    }
+
+    @Override
+    public void logoutBySsoId(List<String> ssoIds) {
+        if (ssoIds == null) return;
+        List<String> sessionIds = new LinkedList<>();
+        for (String id : ssoIds) {
+             String sessionId = idMapper.getSessionFromSSO(id);
+             if (sessionId != null) {
+                 sessionIds.add(sessionId);
+                 idMapper.removeSession(sessionId);
+             }
+
+        }
+        logoutSessionIds(sessionIds);
+    }
+
+    protected void logoutSessionIds(List<String> sessionIds) {
+        sessionIds.forEach(id -> {
+            HttpScope scope = exchange.getScope(Scope.SESSION, id);
+
+            if (scope.exists()) {
+                scope.invalidate();
+            }
+        });
+    }
+
+    @Override
+    public boolean isLoggedIn() {
+        HttpScope session = getSession(false);
+        if (!session.exists()) {
+            log.debug("session was null, returning null");
+            return false;
+        }
+        final SamlSession samlSession = (SamlSession)session.getAttachment(SamlSession.class.getName());
+        if (samlSession == null) {
+            log.debug("SamlSession was not in session, returning null");
+            return false;
+        }
+
+        exchange.authenticationComplete(samlSession);
+        restoreRequest();
+        return true;
+    }
+
+    @Override
+    public void saveAccount(SamlSession account) {
+        HttpScope session = getSession(true);
+        session.setAttachment(SamlSession.class.getName(), account);
+        String sessionId = changeSessionId(session);
+        idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
+
+    }
+
+    protected String changeSessionId(HttpScope session) {
+        if (!deployment.turnOffChangeSessionIdOnLogin()) return session.getID();
+        else return session.getID();
+    }
+
+    @Override
+    public SamlSession getAccount() {
+        HttpScope session = getSession(true);
+        return (SamlSession)session.getAttachment(SamlSession.class.getName());
+    }
+
+    @Override
+    public String getRedirectUri() {
+        HttpScope session = exchange.getScope(Scope.SESSION);
+        String redirect = (String) session.getAttachment(SAML_REDIRECT_URI);
+        if (redirect == null) {
+            URI uri = exchange.getURI();
+            String path = uri.getPath();
+            String relativePath = exchange.getRequest().getRelativePath();
+            String contextPath = path.substring(0, path.indexOf(relativePath));
+
+            if (!contextPath.isEmpty()) {
+                contextPath = contextPath + "/";
+            }
+
+            String baseUri = KeycloakUriBuilder.fromUri(path).replacePath(contextPath).build().toString();
+            return SamlUtil.getRedirectTo(exchange, contextPath, baseUri);
+        }
+        return redirect;
+    }
+
+    @Override
+    public void saveRequest() {
+        exchange.suspendRequest();
+        HttpScope scope = exchange.getScope(Scope.SESSION);
+
+        if (!scope.exists()) {
+            scope.create();
+        }
+
+        KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(exchange.getURI()).replaceQuery(exchange.getURI().getQuery());
+        String uri = uriBuilder.build().toString();
+
+        scope.setAttachment(SAML_REDIRECT_URI, uri);
+    }
+
+    @Override
+    public boolean restoreRequest() {
+        return exchange.restoreRequest();
+    }
+
+    protected HttpScope getSession(boolean create) {
+        HttpScope scope = exchange.getScope(Scope.SESSION);
+
+        if (!scope.exists() && create) {
+            scope.create();
+        }
+
+        return scope;
+    }
+
+    @Override
+    public void logout(boolean glo) {
+        logoutAccount();
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronTokeStore.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronTokeStore.java
new file mode 100644
index 0000000..a658464
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/ElytronTokeStore.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.saml.elytron;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ElytronTokeStore {
+    void logout(boolean glo);
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java
new file mode 100644
index 0000000..94ae592
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.saml.AdapterConstants;
+import org.keycloak.adapters.saml.DefaultSamlDeployment;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlDeploymentContext;
+import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
+import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
+import org.keycloak.saml.common.exceptions.ParsingException;
+
+/**
+ * <p>A {@link ServletContextListener} that parses the keycloak adapter configuration and set the same configuration
+ * as a {@link ServletContext} attribute in order to provide to {@link KeycloakHttpServerAuthenticationMechanism} a way
+ * to obtain the configuration when processing requests.
+ *
+ * <p>This listener should be automatically registered to a deployment using the subsystem.
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakConfigurationServletListener implements ServletContextListener {
+
+    protected static Logger log = Logger.getLogger(KeycloakConfigurationServletListener.class);
+
+    @Override
+    public void contextInitialized(ServletContextEvent sce) {
+        ServletContext servletContext = sce.getServletContext();
+        String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
+        SamlDeploymentContext deploymentContext = null;
+        if (configResolverClass != null) {
+            try {
+                throw new RuntimeException("Not implemented yet");
+                //configResolver = (SamlConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
+                //deploymentContext = new AdapterDeploymentContext(configResolver);
+                //log.info("Using " + configResolverClass + " to resolve Keycloak configuration on a per-request basis.");
+            } catch (Exception ex) {
+                log.warn("The specified resolver " + configResolverClass + " could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: " + ex.getMessage());
+                //deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+            }
+        } else {
+            InputStream is = getConfigInputStream(servletContext);
+            final SamlDeployment deployment;
+            if (is == null) {
+                log.warn("No adapter configuration.  Keycloak is unconfigured and will deny all requests.");
+                deployment = new DefaultSamlDeployment();
+            } else {
+                try {
+                    ResourceLoader loader = new ResourceLoader() {
+                        @Override
+                        public InputStream getResourceAsStream(String resource) {
+                            return servletContext.getResourceAsStream(resource);
+                        }
+                    };
+                    deployment = new DeploymentBuilder().build(is, loader);
+                } catch (ParsingException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            deploymentContext = new SamlDeploymentContext(deployment);
+            servletContext.setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
+            log.debug("Keycloak is using a per-deployment configuration.");
+        }
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent sce) {
+
+    }
+
+    private static InputStream getConfigInputStream(ServletContext context) {
+        InputStream is = getXMLFromServletContext(context);
+        if (is == null) {
+            String path = context.getInitParameter("keycloak.config.file");
+            if (path == null) {
+                log.debug("using /WEB-INF/keycloak-saml.xml");
+                is = context.getResourceAsStream("/WEB-INF/keycloak-saml.xml");
+            } else {
+                try {
+                    is = new FileInputStream(path);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return is;
+    }
+
+    private static InputStream getXMLFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        if (json == null) {
+            return null;
+        }
+        return new ByteArrayInputStream(json.getBytes());
+    }
+}
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
new file mode 100644
index 0000000..9fce501
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanism.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.saml.SamlAuthenticator;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.SamlDeploymentContext;
+import org.keycloak.adapters.spi.AuthChallenge;
+import org.keycloak.adapters.spi.AuthOutcome;
+import org.keycloak.adapters.spi.SessionIdMapper;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpServerAuthenticationMechanism;
+import org.wildfly.security.http.HttpServerRequest;
+import org.wildfly.security.http.Scope;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
+
+    static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
+    static final String NAME = "KEYCLOAK-SAML";
+
+    private final Map<String, ?> properties;
+    private final CallbackHandler callbackHandler;
+    private final SamlDeploymentContext deploymentContext;
+    private final SessionIdMapper idMapper;
+
+    public KeycloakHttpServerAuthenticationMechanism(Map<String, ?> properties, CallbackHandler callbackHandler, SamlDeploymentContext deploymentContext, SessionIdMapper idMapper) {
+        this.properties = properties;
+        this.callbackHandler = callbackHandler;
+        this.deploymentContext = deploymentContext;
+        this.idMapper = idMapper;
+    }
+
+    @Override
+    public String getMechanismName() {
+        return NAME;
+    }
+
+    @Override
+    public void evaluateRequest(HttpServerRequest request) throws HttpAuthenticationException {
+        LOGGER.debugf("Evaluating request for path [%s]", request.getRequestURI());
+        SamlDeploymentContext deploymentContext = getDeploymentContext(request);
+
+        if (deploymentContext == null) {
+            LOGGER.debugf("Ignoring request for path [%s] from mechanism [%s]. No deployment context found.", request.getRequestURI());
+            request.noAuthenticationInProgress();
+            return;
+        }
+
+        ElytronHttpFacade httpFacade = new ElytronHttpFacade(request, idMapper, deploymentContext, callbackHandler);
+        SamlDeployment deployment = httpFacade.getDeployment();
+
+        if (!deployment.isConfigured()) {
+            request.noAuthenticationInProgress();
+            return;
+        }
+
+        if (httpFacade.getRequest().getRelativePath().contains(deployment.getLogoutPage())) {
+            LOGGER.debugf("Ignoring request for [%s] and logout page [%s].", request.getRequestURI(), deployment.getLogoutPage());
+            httpFacade.authenticationCompleteAnonymous();
+            return;
+        }
+
+        SamlAuthenticator authenticator;
+
+        if (httpFacade.getRequest().getRelativePath().endsWith("/saml")) {
+            authenticator = new ElytronSamlEndpoint(httpFacade, deployment);
+        } else {
+            authenticator = new ElytronSamlAuthenticator(httpFacade, deployment, callbackHandler);
+
+        }
+
+        AuthOutcome outcome = authenticator.authenticate();
+
+        if (outcome == AuthOutcome.AUTHENTICATED) {
+            httpFacade.authenticationComplete();
+            return;
+        }
+
+        if (outcome == AuthOutcome.NOT_AUTHENTICATED) {
+            httpFacade.noAuthenticationInProgress(null);
+            return;
+        }
+
+        if (outcome == AuthOutcome.LOGGED_OUT) {
+            if (deployment.getLogoutPage() != null) {
+                redirectLogout(deployment, httpFacade);
+            }
+            httpFacade.authenticationInProgress();
+            return;
+        }
+
+        AuthChallenge challenge = authenticator.getChallenge();
+
+        if (challenge != null) {
+            httpFacade.noAuthenticationInProgress(challenge);
+            return;
+        }
+
+        if (outcome == AuthOutcome.FAILED) {
+            httpFacade.authenticationFailed();
+            return;
+        }
+
+        httpFacade.authenticationInProgress();
+    }
+
+    private SamlDeploymentContext getDeploymentContext(HttpServerRequest request) {
+        if (this.deploymentContext == null) {
+            return (SamlDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(SamlDeploymentContext.class.getName());
+        }
+
+        return this.deploymentContext;
+    }
+
+    protected void redirectLogout(SamlDeployment deployment, ElytronHttpFacade exchange) {
+        String page = deployment.getLogoutPage();
+        sendRedirect(exchange, page);
+        exchange.getResponse().setStatus(302);
+    }
+
+    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);
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java
new file mode 100644
index 0000000..c1b69a4
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakHttpServerAuthenticationMechanismFactory.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.keycloak.adapters.saml.SamlDeploymentContext;
+import org.keycloak.adapters.spi.InMemorySessionIdMapper;
+import org.keycloak.adapters.spi.SessionIdMapper;
+import org.wildfly.security.http.HttpAuthenticationException;
+import org.wildfly.security.http.HttpServerAuthenticationMechanism;
+import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakHttpServerAuthenticationMechanismFactory implements HttpServerAuthenticationMechanismFactory {
+
+    private SessionIdMapper idMapper = new InMemorySessionIdMapper();
+    private final SamlDeploymentContext deploymentContext;
+
+    /**
+     * <p>Creates a new instance.
+     *
+     * <p>A default constructor is necessary in order to allow this factory to be loaded via {@link java.util.ServiceLoader}.
+     */
+    public KeycloakHttpServerAuthenticationMechanismFactory() {
+        this(null);
+    }
+
+    public KeycloakHttpServerAuthenticationMechanismFactory(SamlDeploymentContext deploymentContext) {
+        this.deploymentContext = deploymentContext;
+    }
+
+    @Override
+    public String[] getMechanismNames(Map<String, ?> properties) {
+        return new String[] {KeycloakHttpServerAuthenticationMechanism.NAME};
+    }
+
+    @Override
+    public HttpServerAuthenticationMechanism createAuthenticationMechanism(String mechanismName, Map<String, ?> properties, CallbackHandler callbackHandler) throws HttpAuthenticationException {
+        Map<String, Object> mechanismProperties = new HashMap();
+
+        mechanismProperties.putAll(properties);
+
+        if (KeycloakHttpServerAuthenticationMechanism.NAME.equals(mechanismName)) {
+            return new KeycloakHttpServerAuthenticationMechanism(properties, callbackHandler, this.deploymentContext, idMapper);
+        }
+
+        return null;
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java
new file mode 100644
index 0000000..3207835
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.saml.elytron;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.keycloak.adapters.saml.SamlPrincipal;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.authz.MapAttributes;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.BearerTokenEvidence;
+import org.wildfly.security.evidence.Evidence;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class KeycloakSecurityRealm implements SecurityRealm {
+
+    @Override
+    public RealmIdentity getRealmIdentity(Principal principal) throws RealmUnavailableException {
+        if (principal instanceof SamlPrincipal) {
+            return createRealmIdentity((SamlPrincipal) principal);
+        }
+        return RealmIdentity.NON_EXISTENT;
+    }
+
+    private RealmIdentity createRealmIdentity(SamlPrincipal principal) {
+        return new RealmIdentity() {
+            @Override
+            public Principal getRealmIdentityPrincipal() {
+                return principal;
+            }
+
+            @Override
+            public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+                return SupportLevel.UNSUPPORTED;
+            }
+
+            @Override
+            public <C extends Credential> C getCredential(Class<C> credentialType) throws RealmUnavailableException {
+                return null;
+            }
+
+            @Override
+            public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+                if (isBearerTokenEvidence(evidenceType)) {
+                    return SupportLevel.SUPPORTED;
+                }
+
+                return SupportLevel.UNSUPPORTED;
+            }
+
+            @Override
+            public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
+                return principal != null;
+            }
+
+            @Override
+            public boolean exists() throws RealmUnavailableException {
+                return principal != null;
+            }
+
+            @Override
+            public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+                Map<String, List<String>> attributes = new HashMap<>(principal.getAttributes());
+                return AuthorizationIdentity.basicIdentity(new MapAttributes(attributes));
+            }
+        };
+    }
+
+    @Override
+    public SupportLevel getCredentialAcquireSupport(Class<? extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+        return SupportLevel.UNSUPPORTED;
+    }
+
+    @Override
+    public SupportLevel getEvidenceVerifySupport(Class<? extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+        if (isBearerTokenEvidence(evidenceType)) {
+            return SupportLevel.POSSIBLY_SUPPORTED;
+        }
+
+        return SupportLevel.UNSUPPORTED;
+    }
+
+    private boolean isBearerTokenEvidence(Class<?> evidenceType) {
+        return evidenceType != null && evidenceType.equals(BearerTokenEvidence.class);
+    }
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/SecurityIdentityUtil.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/SecurityIdentityUtil.java
new file mode 100644
index 0000000..ce45db6
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/SecurityIdentityUtil.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.adapters.saml.elytron;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.keycloak.adapters.saml.SamlPrincipal;
+import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
+import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
+import org.wildfly.security.auth.callback.SecurityIdentityCallback;
+import org.wildfly.security.auth.server.SecurityIdentity;
+import org.wildfly.security.evidence.Evidence;
+import org.wildfly.security.http.HttpAuthenticationException;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+final class SecurityIdentityUtil {
+
+    static final SecurityIdentity authorize(CallbackHandler callbackHandler, SamlPrincipal principal) {
+        try {
+            EvidenceVerifyCallback evidenceVerifyCallback = new EvidenceVerifyCallback(new Evidence() {
+                @Override
+                public Principal getPrincipal() {
+                    return principal;
+                }
+            });
+
+            callbackHandler.handle(new Callback[]{evidenceVerifyCallback});
+
+            if (evidenceVerifyCallback.isVerified()) {
+                AuthorizeCallback authorizeCallback = new AuthorizeCallback(null, null);
+
+                try {
+                    callbackHandler.handle(new Callback[] {authorizeCallback});
+                } catch (Exception e) {
+                    throw new HttpAuthenticationException(e);
+                }
+
+                if (authorizeCallback.isAuthorized()) {
+                    SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
+
+                    callbackHandler.handle(new Callback[]{AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
+
+                    SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
+
+                    return securityIdentity;
+                }
+            }
+        } catch (UnsupportedCallbackException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return null;
+    }
+
+}
diff --git a/adapters/saml/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory b/adapters/saml/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory
new file mode 100644
index 0000000..a41c127
--- /dev/null
+++ b/adapters/saml/wildfly-elytron/src/main/resources/META-INF/services/org.wildfly.security.http.HttpServerAuthenticationMechanismFactory
@@ -0,0 +1,19 @@
+#
+# JBoss, Home of Professional Open Source.
+# Copyright 2016 Red Hat, Inc., and individual contributors
+# as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.keycloak.adapters.saml.elytron.KeycloakHttpServerAuthenticationMechanismFactory
\ No newline at end of file
diff --git a/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml b/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
index ece320b..527750f 100755
--- a/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
+++ b/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
@@ -35,6 +35,7 @@
                 <include>org/keycloak/keycloak-jboss-adapter-core/**</include>
                 <include>org/keycloak/keycloak-undertow-adapter/**</include>
                 <include>org/keycloak/keycloak-wildfly-adapter/**</include>
+                <include>org/keycloak/keycloak-wildfly-elytron-oidc-adapter/**</include>
                 <include>org/keycloak/keycloak-wildfly-subsystem/**</include>
                 <include>org/keycloak/keycloak-adapter-subsystem/**</include>
                 <include>org/keycloak/keycloak-servlet-oauth-client/**</include>
diff --git a/distribution/adapters/wildfly-adapter/wildfly-modules/build.xml b/distribution/adapters/wildfly-adapter/wildfly-modules/build.xml
index a534b4f..8e608a5 100755
--- a/distribution/adapters/wildfly-adapter/wildfly-modules/build.xml
+++ b/distribution/adapters/wildfly-adapter/wildfly-modules/build.xml
@@ -77,6 +77,10 @@
         <module-def name="org.keycloak.keycloak-authz-client">
             <maven-resource group="org.keycloak" artifact="keycloak-authz-client"/>
         </module-def>
+
+        <module-def name="org.keycloak.keycloak-wildfly-elytron-oidc-adapter">
+            <maven-resource group="org.keycloak" artifact="keycloak-wildfly-elytron-oidc-adapter"/>
+        </module-def>
     </target>
 
     <target name="clean-target">
diff --git a/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml b/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml
index b5a3d5e..00eef58 100755
--- a/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml
+++ b/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml
@@ -68,6 +68,10 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-wildfly-subsystem</artifactId>
         </dependency>
         <dependency>
diff --git a/distribution/adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-elytron-oidc-adapter/main/module.xml b/distribution/adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-elytron-oidc-adapter/main/module.xml
new file mode 100755
index 0000000..1ca9839
--- /dev/null
+++ b/distribution/adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-elytron-oidc-adapter/main/module.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2016 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-wildfly-elytron-oidc-adapter">
+    <properties>
+        <property name="jboss.api" value="private"/>
+    </properties>
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="javax.api"/>
+        <module name="org.bouncycastle" />
+        <module name="com.fasterxml.jackson.core.jackson-annotations"/>
+        <module name="com.fasterxml.jackson.core.jackson-core"/>
+        <module name="com.fasterxml.jackson.core.jackson-databind"/>
+        <module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
+        <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-spi"/>
+        <module name="org.keycloak.keycloak-adapter-core"/>
+        <module name="org.keycloak.keycloak-core"/>
+        <module name="org.keycloak.keycloak-common"/>
+        <module name="org.wildfly.security.elytron"/>
+    </dependencies>
+
+</module>
diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
index b91b2dc..ff57870 100755
--- a/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
+++ b/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/assembly.xml
@@ -37,6 +37,7 @@
                 <include>org/keycloak/keycloak-jboss-adapter-core/**</include>
                 <include>org/keycloak/keycloak-saml-undertow-adapter/**</include>
                 <include>org/keycloak/keycloak-saml-wildfly-adapter/**</include>
+                <include>org/keycloak/keycloak-saml-wildfly-elytron-adapter/**</include>
                 <include>org/keycloak/keycloak-saml-wildfly-subsystem/**</include>
                 <include>org/keycloak/keycloak-saml-adapter-subsystem/**</include>
             </includes>
diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/build.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/build.xml
index abbe9d3..885ed81 100755
--- a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/build.xml
+++ b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/build.xml
@@ -76,6 +76,10 @@
             <maven-resource group="org.keycloak" artifact="keycloak-saml-wildfly-subsystem"/>
         </module-def>
 
+        <module-def name="org.keycloak.keycloak-saml-wildfly-elytron-adapter">
+            <maven-resource group="org.keycloak" artifact="keycloak-saml-wildfly-elytron-adapter"/>
+        </module-def>
+
     </target>
 
     <target name="clean-target">
diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml
index 06f0ded..026d869 100755
--- a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml
+++ b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml
@@ -72,6 +72,10 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-wildfly-elytron-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-saml-wildfly-subsystem</artifactId>
         </dependency>
     </dependencies>
diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-saml-wildfly-elytron-adapter/main/module.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-saml-wildfly-elytron-adapter/main/module.xml
new file mode 100755
index 0000000..393eac9
--- /dev/null
+++ b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/src/main/resources/modules/org/keycloak/keycloak-saml-wildfly-elytron-adapter/main/module.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<!--
+  ~ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ * and other contributors as indicated by the @author tags.
+  ~ *
+  ~ * Licensed under the Apache License, Version 2.0 (the "License");
+  ~ * you may not use this file except in compliance with the License.
+  ~ * You may obtain a copy of the License at
+  ~ *
+  ~ * http://www.apache.org/licenses/LICENSE-2.0
+  ~ *
+  ~ * Unless required by applicable law or agreed to in writing, software
+  ~ * distributed under the License is distributed on an "AS IS" BASIS,
+  ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ * See the License for the specific language governing permissions and
+  ~ * limitations under the License.
+  -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-wildfly-elytron-adapter">
+    <properties>
+        <property name="jboss.api" value="private"/>
+    </properties>
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="javax.api"/>
+        <module name="org.bouncycastle" />
+        <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-saml-undertow-adapter"/>
+        <module name="org.keycloak.keycloak-adapter-spi"/>
+        <module name="org.keycloak.keycloak-saml-core-public"/>
+        <module name="org.keycloak.keycloak-saml-core"/>
+        <module name="org.keycloak.keycloak-saml-adapter-api-public"/>
+        <module name="org.keycloak.keycloak-saml-adapter-core"/>
+        <module name="org.keycloak.keycloak-common"/>
+        <module name="org.apache.httpcomponents"/>
+        <module name="org.infinispan"/>
+        <module name="org.infinispan.commons"/>
+        <module name="org.infinispan.cachestore.remote"/>
+        <module name="org.infinispan.client.hotrod"/>
+        <module name="org.wildfly.security.elytron"/>
+    </dependencies>
+
+</module>
diff --git a/elytron/standalone-elytron.xml b/elytron/standalone-elytron.xml
new file mode 100644
index 0000000..4237b02
--- /dev/null
+++ b/elytron/standalone-elytron.xml
@@ -0,0 +1,558 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<server xmlns="urn:jboss:domain:5.0">
+
+    <extensions>
+        <extension module="org.jboss.as.clustering.infinispan"/>
+        <extension module="org.jboss.as.connector"/>
+        <extension module="org.jboss.as.deployment-scanner"/>
+        <extension module="org.jboss.as.ee"/>
+        <extension module="org.jboss.as.ejb3"/>
+        <extension module="org.jboss.as.jaxrs"/>
+        <extension module="org.jboss.as.jdr"/>
+        <extension module="org.jboss.as.jmx"/>
+        <extension module="org.jboss.as.jpa"/>
+        <extension module="org.jboss.as.jsf"/>
+        <extension module="org.jboss.as.logging"/>
+        <extension module="org.jboss.as.mail"/>
+        <extension module="org.jboss.as.naming"/>
+        <extension module="org.jboss.as.pojo"/>
+        <extension module="org.jboss.as.remoting"/>
+        <extension module="org.jboss.as.sar"/>
+        <extension module="org.jboss.as.security"/>
+        <extension module="org.jboss.as.transactions"/>
+        <extension module="org.jboss.as.webservices"/>
+        <extension module="org.jboss.as.weld"/>
+        <extension module="org.wildfly.extension.batch.jberet"/>
+        <extension module="org.wildfly.extension.bean-validation"/>
+        <extension module="org.wildfly.extension.core-management"/>
+        <extension module="org.wildfly.extension.elytron"/>
+        <extension module="org.wildfly.extension.io"/>
+        <extension module="org.wildfly.extension.request-controller"/>
+        <extension module="org.wildfly.extension.security.manager"/>
+        <extension module="org.wildfly.extension.undertow"/>
+        <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+    </extensions>
+
+
+    <management>
+        <security-realms>
+            <security-realm name="ManagementRealm">
+                <authentication>
+                    <local default-user="$local" skip-group-loading="true"/>
+                    <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization map-groups-to-roles="false">
+                    <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+            <security-realm name="ApplicationRealm">
+                <server-identities>
+                    <ssl>
+                        <keystore path="application.keystore" relative-to="jboss.server.config.dir" keystore-password="password" alias="server" key-password="password" generate-self-signed-certificate-host="localhost"/>
+                    </ssl>
+                </server-identities>
+                <authentication>
+                    <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
+                    <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization>
+                    <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+        </security-realms>
+        <audit-log>
+            <formatters>
+                <json-formatter name="json-formatter"/>
+            </formatters>
+            <handlers>
+                <file-handler name="file" formatter="json-formatter" path="audit-log.log" relative-to="jboss.server.data.dir"/>
+            </handlers>
+            <logger log-boot="true" log-read-only="false" enabled="false">
+                <handlers>
+                    <handler name="file"/>
+                </handlers>
+            </logger>
+        </audit-log>
+        <management-interfaces>
+            <http-interface security-realm="ManagementRealm">
+                <http-upgrade enabled="true" sasl-authentication-factory="keycloak-sasl-authentication"/>
+                <socket-binding http="management-http"/>
+            </http-interface>
+        </management-interfaces>
+        <access-control provider="rbac" use-identity-roles="true"/>
+    </management>
+
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:logging:3.0">
+            <console-handler name="CONSOLE">
+                <level name="INFO"/>
+                <formatter>
+                    <named-formatter name="COLOR-PATTERN"/>
+                </formatter>
+            </console-handler>
+            <periodic-rotating-file-handler name="FILE" autoflush="true">
+                <formatter>
+                    <named-formatter name="PATTERN"/>
+                </formatter>
+                <file relative-to="jboss.server.log.dir" path="server.log"/>
+                <suffix value=".yyyy-MM-dd"/>
+                <append value="true"/>
+            </periodic-rotating-file-handler>
+            <logger category="com.arjuna">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.jboss.as.config">
+                <level name="DEBUG"/>
+            </logger>
+            <logger category="sun.rmi">
+                <level name="WARN"/>
+            </logger>
+            <root-logger>
+                <level name="INFO"/>
+                <handlers>
+                    <handler name="CONSOLE"/>
+                    <handler name="FILE"/>
+                </handlers>
+            </root-logger>
+            <formatter name="PATTERN">
+                <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+            <formatter name="COLOR-PATTERN">
+                <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:batch-jberet:2.0">
+            <default-job-repository name="in-memory"/>
+            <default-thread-pool name="batch"/>
+            <job-repository name="in-memory">
+                <in-memory/>
+            </job-repository>
+            <thread-pool name="batch">
+                <max-threads count="10"/>
+                <keepalive-time time="30" unit="seconds"/>
+            </thread-pool>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:datasources:5.0">
+            <datasources>
+                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
+                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
+                    <driver>h2</driver>
+                    <security>
+                        <user-name>sa</user-name>
+                        <password>sa</password>
+                    </security>
+                </datasource>
+                <drivers>
+                    <driver name="h2" module="com.h2database.h2">
+                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+                    </driver>
+                </drivers>
+            </datasources>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
+            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ee:4.0">
+            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
+            <concurrent>
+                <context-services>
+                    <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
+                </context-services>
+                <managed-thread-factories>
+                    <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
+                </managed-thread-factories>
+                <managed-executor-services>
+                    <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
+                </managed-executor-services>
+                <managed-scheduled-executor-services>
+                    <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
+                </managed-scheduled-executor-services>
+            </concurrent>
+            <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ejb3:5.0">
+            <session-bean>
+                <stateless>
+                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+                </stateless>
+                <stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
+                <singleton default-access-timeout="5000"/>
+            </session-bean>
+            <pools>
+                <bean-instance-pools>
+                    <strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                    <strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                </bean-instance-pools>
+            </pools>
+            <caches>
+                <cache name="simple"/>
+                <cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/>
+            </caches>
+            <passivation-stores>
+                <passivation-store name="infinispan" cache-container="ejb" max-size="10000"/>
+            </passivation-stores>
+            <async thread-pool-name="default"/>
+            <timer-service thread-pool-name="default" default-data-store="default-file-store">
+                <data-stores>
+                    <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
+                </data-stores>
+            </timer-service>
+            <remote connector-ref="http-remoting-connector" thread-pool-name="default">
+                <channel-creation-options>
+                    <option name="READ_TIMEOUT" value="${prop.remoting-connector.read.timeout:20}" type="xnio"/>
+                    <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
+                </channel-creation-options>
+            </remote>
+            <thread-pools>
+                <thread-pool name="default">
+                    <max-threads count="10"/>
+                    <keepalive-time time="100" unit="milliseconds"/>
+                </thread-pool>
+            </thread-pools>
+            <default-security-domain value="other"/>
+            <default-missing-method-permissions-deny-access value="true"/>
+            <log-system-exceptions value="true"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:io:1.1">
+            <worker name="default"/>
+            <buffer-pool name="default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:infinispan:4.0">
+            <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
+                <local-cache name="default">
+                    <transaction mode="BATCH"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+                <local-cache name="concurrent">
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="ejb" aliases="sfsb" default-cache="passivation" module="org.wildfly.clustering.ejb.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="hibernate" module="org.hibernate.infinispan">
+                <local-cache name="entity">
+                    <transaction mode="NON_XA"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="local-query">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="timestamps"/>
+            </cache-container>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jca:5.0">
+            <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
+            <bean-validation enabled="true"/>
+            <default-workmanager>
+                <short-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </short-running-threads>
+                <long-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </long-running-threads>
+            </default-workmanager>
+            <cached-connection-manager/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
+            <expose-resolved-model/>
+            <expose-expression-model/>
+            <remoting-connector/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jpa:1.1">
+            <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jsf:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:mail:2.1">
+            <mail-session name="default" jndi-name="java:jboss/mail/Default">
+                <smtp-server outbound-socket-binding-ref="mail-smtp"/>
+            </mail-session>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:naming:2.0">
+            <remote-naming/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:remoting:4.0">
+            <endpoint/>
+            <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:resource-adapters:5.0"/>
+        <subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:security-manager:3.0">
+            <deployment-permissions>
+                <maximum-set>
+                    <permission class="java.security.AllPermission"/>
+                </maximum-set>
+            </deployment-permissions>
+        </subsystem>
+        <subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers">
+            <providers>
+                <aggregate-providers name="combined-providers">
+                    <providers name="elytron"/>
+                    <providers name="openssl"/>
+                </aggregate-providers>
+                <provider-loader name="elytron" module="org.wildfly.security.elytron"/>
+                <provider-loader name="openssl" module="org.wildfly.openssl"/>
+            </providers>
+            <audit-logging>
+                <file-audit-log name="local-audit" path="audit.log" relative-to="jboss.server.log.dir" format="JSON"/>
+            </audit-logging>
+            <security-domains>
+                <security-domain name="ApplicationDomain" default-realm="ApplicationRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                    <realm name="ApplicationRealm" role-decoder="groups-to-roles"/>
+                    <realm name="local"/>
+                </security-domain>
+                <security-domain name="ManagementDomain" default-realm="ManagementRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                    <realm name="ManagementRealm" role-decoder="groups-to-roles"/>
+                    <realm name="local" role-mapper="super-user-mapper"/>
+                </security-domain>
+                <security-domain name="KeycloakSecurityDomain" default-realm="wildfly-cli" permission-mapper="default-permission-mapper">
+                    <realm name="wildfly-cli" role-decoder="groups-to-roles"/>
+                </security-domain>
+            </security-domains>
+            <security-realms>
+                <identity-realm name="local" identity="$local"/>
+                <properties-realm name="ApplicationRealm">
+                    <users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ApplicationRealm"/>
+                    <groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </properties-realm>
+                <properties-realm name="ManagementRealm">
+                    <users-properties path="mgmt-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ManagementRealm"/>
+                    <groups-properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </properties-realm>
+                <custom-realm name="KeycloakRealm" class-name="org.keycloak.adapters.elytron.KeycloakSecurityRealm" module="org.keycloak.keycloak-wildfly-elytron-oidc-adapter" />
+            </security-realms>
+            <mappers>
+                <constant-permission-mapper name="default-permission-mapper">
+                    <permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
+                    <permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/>
+                    <permission class-name="org.wildfly.transaction.client.RemoteTransactionPermission" module="org.wildfly.transaction.client"/>
+                    <permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
+                </constant-permission-mapper>
+                <constant-realm-mapper name="local" realm-name="local"/>
+                <simple-role-decoder name="groups-to-roles" attribute="groups"/>
+                <constant-role-mapper name="super-user-mapper">
+                    <role name="SuperUser"/>
+                </constant-role-mapper>
+            </mappers>
+            <http>
+                <http-authentication-factory name="management-http-authentication" http-server-mechanism-factory="global" security-domain="ManagementDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="DIGEST">
+                            <mechanism-realm realm-name="ManagementRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </http-authentication-factory>
+                <http-authentication-factory name="application-http-authentication" http-server-mechanism-factory="global" security-domain="ApplicationDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="BASIC">
+                            <mechanism-realm realm-name="Application Realm"/>
+                        </mechanism>
+                        <mechanism mechanism-name="FORM"/>
+                    </mechanism-configuration>
+                </http-authentication-factory>
+                <provider-http-server-mechanism-factory name="global"/>
+            </http>
+            <sasl>
+                <sasl-authentication-factory name="keycloak-sasl-authentication" sasl-server-factory="configured" security-domain="KeycloakSecurityDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
+                        <mechanism mechanism-name="DIGEST-MD5">
+                            <mechanism-realm realm-name="ManagementRealm"/>
+                        </mechanism>
+                        <mechanism mechanism-name="OAUTHBEARER"/>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <sasl-authentication-factory name="management-sasl-authentication" sasl-server-factory="configured" security-domain="ManagementDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
+                        <mechanism mechanism-name="DIGEST-MD5">
+                            <mechanism-realm realm-name="ManagementRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
+                        <mechanism mechanism-name="DIGEST-MD5">
+                            <mechanism-realm realm-name="ApplicationRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <configurable-sasl-server-factory name="configured" sasl-server-factory="elytron">
+                    <properties>
+                        <property name="wildfly.sasl.local-user.default-user" value="$local"/>
+                    </properties>
+                    <filters>
+                        <filter>
+                            <pattern-filter value="JBOSS-LOCAL-USER"/>
+                        </filter>
+                        <filter>
+                            <pattern-filter value="DIGEST-MD5"/>
+                        </filter>
+                        <filter>
+                            <pattern-filter value="OAUTHBEARER"/>
+                        </filter>
+                    </filters>
+                </configurable-sasl-server-factory>
+                <mechanism-provider-filtering-sasl-server-factory name="elytron" sasl-server-factory="global">
+                    <filters>
+                        <filter provider-name="WildFlyElytron"/>
+                    </filters>
+                </mechanism-provider-filtering-sasl-server-factory>
+                <provider-sasl-server-factory name="global"/>
+            </sasl>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:security:3.0">
+            <security-domains>
+                <security-domain name="other" cache-type="default">
+                    <authentication>
+                        <login-module code="Remoting" flag="optional">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                        <login-module code="RealmDirect" flag="required">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                    </authentication>
+                </security-domain>
+                <security-domain name="jboss-web-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jboss-ejb-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jaspitest" cache-type="default">
+                    <authentication-jaspi>
+                        <login-module-stack name="dummy">
+                            <login-module code="Dummy" flag="optional"/>
+                        </login-module-stack>
+                        <auth-module code="Dummy"/>
+                    </authentication-jaspi>
+                </security-domain>
+                <security-domain name="keycloak">
+                    <authentication>
+                        <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule" flag="required"/>
+                    </authentication>
+                </security-domain>
+            </security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:transactions:3.1">
+            <core-environment>
+                <process-id>
+                    <uuid/>
+                </process-id>
+            </core-environment>
+            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+            <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:undertow:4.0">
+            <buffer-cache name="default"/>
+            <server name="default-server">
+                <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
+                <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
+                <host name="default-host" alias="localhost">
+                    <location name="/" handler="welcome-content"/>
+                    <filter-ref name="server-header"/>
+                    <filter-ref name="x-powered-by-header"/>
+                    <http-invoker http-authentication-factory="application-http-authentication"/>
+                </host>
+            </server>
+            <servlet-container name="default">
+                <jsp-config/>
+                <websockets/>
+            </servlet-container>
+            <handlers>
+                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
+            </handlers>
+            <filters>
+                <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
+                <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
+            </filters>
+            <application-security-domains>
+                <application-security-domain name="other" http-authentication-factory="keycloak-http-authentication-factory"/>
+            </application-security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:webservices:2.0">
+            <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
+            <endpoint-config name="Standard-Endpoint-Config"/>
+            <endpoint-config name="Recording-Endpoint-Config">
+                <pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
+                    <handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
+                </pre-handler-chain>
+            </endpoint-config>
+            <client-config name="Standard-Client-Config"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:weld:4.0"/>
+        <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
+            <realm name="wildfly">
+                <realm-public-key>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqVOcTeth98Fi9T/9GMK9q7w6Wvft1Xc+aMFTru5vcsqh0NL1hYRuSdqxTK0lpbaTfDLF+bh1QP+1ZArjLEshNoddsc39Lf4xDh9smh1xOp/GcFQSDmSz9dQ8FmQUagnNtwIWSXVphGyK5yOznqIzrV/TNHuGvUA5MsPNkm99LrQlODLYr6hsE/kPoKMybi8z/tYkLJXtXS8ZM5O/2rOrPNcqvw58Fb1pJ0OXO59zK96qw/eqRnPPbi3N0FRQLKCG51DpQu6xe8zKHwEtUXDGdtgSceA6jKynmAG/dWrBEARczgAPbUlEIq3HByrtB1DHR0cZKUYVj5PwkGEg6IgXhwIDAQAB</realm-public-key>
+                <auth-server-url>http://localhost:8180/auth</auth-server-url>
+                <ssl-required>none</ssl-required>
+            </realm>
+            <secure-deployment name="wildfly-cli">
+                <realm>wildfly</realm>
+                <resource>wildfly-cli</resource>
+            </secure-deployment>
+        </subsystem>
+    </profile>
+
+    <interfaces>
+        <interface name="management">
+            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+        </interface>
+        <interface name="public">
+            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+        </interface>
+    </interfaces>
+
+    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
+        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
+        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
+        <socket-binding name="http" port="${jboss.http.port:8080}"/>
+        <socket-binding name="https" port="${jboss.https.port:8443}"/>
+        <socket-binding name="txn-recovery-environment" port="4712"/>
+        <socket-binding name="txn-status-manager" port="4713"/>
+        <outbound-socket-binding name="mail-smtp">
+            <remote-destination host="localhost" port="25"/>
+        </outbound-socket-binding>
+    </socket-binding-group>
+</server>
\ No newline at end of file
diff --git a/elytron/standalone-oauth2-sasl-with-elytron-only.xml b/elytron/standalone-oauth2-sasl-with-elytron-only.xml
new file mode 100644
index 0000000..dde9d8b
--- /dev/null
+++ b/elytron/standalone-oauth2-sasl-with-elytron-only.xml
@@ -0,0 +1,547 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!--
+  ~ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ * and other contributors as indicated by the @author tags.
+  ~ *
+  ~ * Licensed under the Apache License, Version 2.0 (the "License");
+  ~ * you may not use this file except in compliance with the License.
+  ~ * You may obtain a copy of the License at
+  ~ *
+  ~ * http://www.apache.org/licenses/LICENSE-2.0
+  ~ *
+  ~ * Unless required by applicable law or agreed to in writing, software
+  ~ * distributed under the License is distributed on an "AS IS" BASIS,
+  ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ * See the License for the specific language governing permissions and
+  ~ * limitations under the License.
+  -->
+
+<server xmlns="urn:jboss:domain:5.0">
+    <extensions>
+        <extension module="org.jboss.as.clustering.infinispan"/>
+        <extension module="org.jboss.as.connector"/>
+        <extension module="org.jboss.as.deployment-scanner"/>
+        <extension module="org.jboss.as.ee"/>
+        <extension module="org.jboss.as.ejb3"/>
+        <extension module="org.jboss.as.jaxrs"/>
+        <extension module="org.jboss.as.jdr"/>
+        <extension module="org.jboss.as.jmx"/>
+        <extension module="org.jboss.as.jpa"/>
+        <extension module="org.jboss.as.jsf"/>
+        <extension module="org.jboss.as.logging"/>
+        <extension module="org.jboss.as.mail"/>
+        <extension module="org.jboss.as.naming"/>
+        <extension module="org.jboss.as.pojo"/>
+        <extension module="org.jboss.as.remoting"/>
+        <extension module="org.jboss.as.sar"/>
+        <extension module="org.jboss.as.security"/>
+        <extension module="org.jboss.as.transactions"/>
+        <extension module="org.jboss.as.webservices"/>
+        <extension module="org.jboss.as.weld"/>
+        <extension module="org.wildfly.extension.batch.jberet"/>
+        <extension module="org.wildfly.extension.bean-validation"/>
+        <extension module="org.wildfly.extension.core-management"/>
+        <extension module="org.wildfly.extension.elytron"/>
+        <extension module="org.wildfly.extension.io"/>
+        <extension module="org.wildfly.extension.request-controller"/>
+        <extension module="org.wildfly.extension.security.manager"/>
+        <extension module="org.wildfly.extension.undertow"/>
+    </extensions>
+    <management>
+        <security-realms>
+            <security-realm name="ManagementRealm">
+                <authentication>
+                    <local default-user="$local" skip-group-loading="true"/>
+                    <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization map-groups-to-roles="false">
+                    <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+            <security-realm name="ApplicationRealm">
+                <server-identities>
+                    <ssl>
+                        <keystore path="application.keystore" relative-to="jboss.server.config.dir" keystore-password="password" alias="server" key-password="password" generate-self-signed-certificate-host="localhost"/>
+                    </ssl>
+                </server-identities>
+                <authentication>
+                    <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
+                    <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization>
+                    <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+        </security-realms>
+        <audit-log>
+            <formatters>
+                <json-formatter name="json-formatter"/>
+            </formatters>
+            <handlers>
+                <file-handler name="file" formatter="json-formatter" path="audit-log.log" relative-to="jboss.server.data.dir"/>
+            </handlers>
+            <logger log-boot="true" log-read-only="false" enabled="false">
+                <handlers>
+                    <handler name="file"/>
+                </handlers>
+            </logger>
+        </audit-log>
+        <management-interfaces>
+            <http-interface security-realm="ManagementRealm">
+                <http-upgrade enabled="true" sasl-authentication-factory="oauth2-sasl-authentication"/>
+                <socket-binding http="management-http"/>
+            </http-interface>
+        </management-interfaces>
+        <access-control provider="rbac" use-identity-roles="true"/>
+    </management>
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:logging:3.0">
+            <console-handler name="CONSOLE">
+                <level name="INFO"/>
+                <formatter>
+                    <named-formatter name="COLOR-PATTERN"/>
+                </formatter>
+            </console-handler>
+            <periodic-rotating-file-handler name="FILE" autoflush="true">
+                <formatter>
+                    <named-formatter name="PATTERN"/>
+                </formatter>
+                <file relative-to="jboss.server.log.dir" path="server.log"/>
+                <suffix value=".yyyy-MM-dd"/>
+                <append value="true"/>
+            </periodic-rotating-file-handler>
+            <logger category="com.arjuna">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.jboss.as.config">
+                <level name="DEBUG"/>
+            </logger>
+            <logger category="sun.rmi">
+                <level name="WARN"/>
+            </logger>
+            <root-logger>
+                <level name="INFO"/>
+                <handlers>
+                    <handler name="CONSOLE"/>
+                    <handler name="FILE"/>
+                </handlers>
+            </root-logger>
+            <formatter name="PATTERN">
+                <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+            <formatter name="COLOR-PATTERN">
+                <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:batch-jberet:2.0">
+            <default-job-repository name="in-memory"/>
+            <default-thread-pool name="batch"/>
+            <job-repository name="in-memory">
+                <in-memory/>
+            </job-repository>
+            <thread-pool name="batch">
+                <max-threads count="10"/>
+                <keepalive-time time="30" unit="seconds"/>
+            </thread-pool>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:core-management:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:datasources:5.0">
+            <datasources>
+                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
+                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
+                    <driver>h2</driver>
+                    <security>
+                        <user-name>sa</user-name>
+                        <password>sa</password>
+                    </security>
+                </datasource>
+                <drivers>
+                    <driver name="h2" module="com.h2database.h2">
+                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+                    </driver>
+                </drivers>
+            </datasources>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
+            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ee:4.0">
+            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
+            <concurrent>
+                <context-services>
+                    <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
+                </context-services>
+                <managed-thread-factories>
+                    <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
+                </managed-thread-factories>
+                <managed-executor-services>
+                    <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
+                </managed-executor-services>
+                <managed-scheduled-executor-services>
+                    <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
+                </managed-scheduled-executor-services>
+            </concurrent>
+            <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ejb3:5.0">
+            <session-bean>
+                <stateless>
+                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+                </stateless>
+                <stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
+                <singleton default-access-timeout="5000"/>
+            </session-bean>
+            <pools>
+                <bean-instance-pools>
+                    <strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                    <strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                </bean-instance-pools>
+            </pools>
+            <caches>
+                <cache name="simple"/>
+                <cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/>
+            </caches>
+            <passivation-stores>
+                <passivation-store name="infinispan" cache-container="ejb" max-size="10000"/>
+            </passivation-stores>
+            <async thread-pool-name="default"/>
+            <timer-service thread-pool-name="default" default-data-store="default-file-store">
+                <data-stores>
+                    <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
+                </data-stores>
+            </timer-service>
+            <remote connector-ref="http-remoting-connector" thread-pool-name="default">
+                <channel-creation-options>
+                    <option name="READ_TIMEOUT" value="${prop.remoting-connector.read.timeout:20}" type="xnio"/>
+                    <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/>
+                </channel-creation-options>
+            </remote>
+            <thread-pools>
+                <thread-pool name="default">
+                    <max-threads count="10"/>
+                    <keepalive-time time="100" unit="milliseconds"/>
+                </thread-pool>
+            </thread-pools>
+            <default-security-domain value="other"/>
+            <default-missing-method-permissions-deny-access value="true"/>
+            <log-system-exceptions value="true"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:io:1.1">
+            <worker name="default"/>
+            <buffer-pool name="default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:infinispan:4.0">
+            <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
+                <local-cache name="default">
+                    <transaction mode="BATCH"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+                <local-cache name="concurrent">
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="ejb" aliases="sfsb" default-cache="passivation" module="org.wildfly.clustering.ejb.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="hibernate" module="org.hibernate.infinispan">
+                <local-cache name="entity">
+                    <transaction mode="NON_XA"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="local-query">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="timestamps"/>
+            </cache-container>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jca:5.0">
+            <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
+            <bean-validation enabled="true"/>
+            <default-workmanager>
+                <short-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </short-running-threads>
+                <long-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </long-running-threads>
+            </default-workmanager>
+            <cached-connection-manager/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
+            <expose-resolved-model/>
+            <expose-expression-model/>
+            <remoting-connector/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jpa:1.1">
+            <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jsf:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:mail:2.1">
+            <mail-session name="default" jndi-name="java:jboss/mail/Default">
+                <smtp-server outbound-socket-binding-ref="mail-smtp"/>
+            </mail-session>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:naming:2.0">
+            <remote-naming/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:remoting:4.0">
+            <endpoint/>
+            <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:resource-adapters:5.0"/>
+        <subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:security-manager:3.0">
+            <deployment-permissions>
+                <maximum-set>
+                    <permission class="java.security.AllPermission"/>
+                </maximum-set>
+            </deployment-permissions>
+        </subsystem>
+        <subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers">
+            <providers>
+                <provider-loader name="elytron" module="org.wildfly.security.elytron"/>
+                <provider-loader name="openssl" module="org.wildfly.openssl"/>
+                <aggregate-providers name="combined-providers">
+                    <providers name="elytron"/>
+                    <providers name="openssl"/>
+                </aggregate-providers>
+            </providers>
+            <audit-logging>
+                <file-audit-log name="local-audit" path="audit.log" relative-to="jboss.server.log.dir" format="JSON"/>
+            </audit-logging>
+            <security-domains>
+                <security-domain name="ApplicationDomain" default-realm="ApplicationRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                    <realm name="ApplicationRealm" role-decoder="groups-to-roles"/>
+                    <realm name="local"/>
+                </security-domain>
+                <security-domain name="ManagementDomain" default-realm="ManagementRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                    <realm name="ManagementRealm" role-decoder="groups-to-roles"/>
+                    <realm name="local" role-mapper="super-user-mapper"/>
+                </security-domain>
+                <security-domain name="OAuth2Domain" default-realm="JwtRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                    <realm name="JwtRealm" role-decoder="groups-to-roles"/>
+                </security-domain>
+            </security-domains>
+            <security-realms>
+                <identity-realm name="local" identity="$local"/>
+                <properties-realm name="ApplicationRealm">
+                    <users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ApplicationRealm"/>
+                    <groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </properties-realm>
+                <properties-realm name="ManagementRealm">
+                    <users-properties path="mgmt-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="ManagementRealm"/>
+                    <groups-properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </properties-realm>
+                <token-realm name="JwtRealm" principal-claim="preferred_username">
+                    <jwt/>
+                </token-realm>
+            </security-realms>
+            <mappers>
+                <constant-permission-mapper name="default-permission-mapper">
+                    <permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
+                    <permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/>
+                    <permission class-name="org.wildfly.transaction.client.RemoteTransactionPermission" module="org.wildfly.transaction.client"/>
+                    <permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/>
+                </constant-permission-mapper>
+                <constant-realm-mapper name="local" realm-name="local"/>
+                <simple-role-decoder name="groups-to-roles" attribute="groups"/>
+                <constant-role-mapper name="super-user-mapper">
+                    <role name="SuperUser"/>
+                </constant-role-mapper>
+            </mappers>
+            <http>
+                <http-authentication-factory name="management-http-authentication" http-server-mechanism-factory="global" security-domain="ManagementDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="DIGEST">
+                            <mechanism-realm realm-name="ManagementRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </http-authentication-factory>
+                <http-authentication-factory name="application-http-authentication" http-server-mechanism-factory="global" security-domain="ApplicationDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="BASIC">
+                            <mechanism-realm realm-name="Application Realm"/>
+                        </mechanism>
+                        <mechanism mechanism-name="FORM"/>
+                    </mechanism-configuration>
+                </http-authentication-factory>
+                <provider-http-server-mechanism-factory name="global"/>
+            </http>
+            <sasl>
+                <sasl-authentication-factory name="oauth2-sasl-authentication" sasl-server-factory="configured" security-domain="OAuth2Domain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="OAUTHBEARER"/>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <sasl-authentication-factory name="management-sasl-authentication" sasl-server-factory="configured" security-domain="ManagementDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
+                        <mechanism mechanism-name="DIGEST-MD5">
+                            <mechanism-realm realm-name="ManagementRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
+                    <mechanism-configuration>
+                        <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
+                        <mechanism mechanism-name="DIGEST-MD5">
+                            <mechanism-realm realm-name="ApplicationRealm"/>
+                        </mechanism>
+                    </mechanism-configuration>
+                </sasl-authentication-factory>
+                <provider-sasl-server-factory name="global"/>
+                <mechanism-provider-filtering-sasl-server-factory name="elytron" sasl-server-factory="global">
+                    <filters>
+                        <filter provider-name="WildFlyElytron"/>
+                    </filters>
+                </mechanism-provider-filtering-sasl-server-factory>
+                <configurable-sasl-server-factory name="configured" sasl-server-factory="elytron">
+                    <filters>
+                        <filter>
+                            <pattern-filter value="JBOSS-LOCAL-USER"/>
+                        </filter>
+                        <filter>
+                            <pattern-filter value="DIGEST-MD5"/>
+                        </filter>
+                        <filter>
+                            <pattern-filter value="OAUTHBEARER"/>
+                        </filter>
+                    </filters>
+                    <properties>
+                        <property name="wildfly.sasl.local-user.default-user" value="$local"/>
+                    </properties>
+                </configurable-sasl-server-factory>
+            </sasl>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:security:3.0">
+            <security-domains>
+                <security-domain name="other" cache-type="default">
+                    <authentication>
+                        <login-module code="Remoting" flag="optional">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                        <login-module code="RealmDirect" flag="required">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                    </authentication>
+                </security-domain>
+                <security-domain name="jboss-web-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jboss-ejb-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jaspitest" cache-type="default">
+                    <authentication-jaspi>
+                        <login-module-stack name="dummy">
+                            <login-module code="Dummy" flag="optional"/>
+                        </login-module-stack>
+                        <auth-module code="Dummy"/>
+                    </authentication-jaspi>
+                </security-domain>
+            </security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:transactions:3.1">
+            <core-environment>
+                <process-id>
+                    <uuid/>
+                </process-id>
+            </core-environment>
+            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+            <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:undertow:4.0">
+            <buffer-cache name="default"/>
+            <server name="default-server">
+                <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
+                <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
+                <host name="default-host" alias="localhost">
+                    <location name="/" handler="welcome-content"/>
+                    <filter-ref name="server-header"/>
+                    <filter-ref name="x-powered-by-header"/>
+                    <http-invoker http-authentication-factory="application-http-authentication"/>
+                </host>
+            </server>
+            <servlet-container name="default">
+                <jsp-config/>
+                <websockets/>
+            </servlet-container>
+            <handlers>
+                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
+            </handlers>
+            <filters>
+                <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
+                <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
+            </filters>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:webservices:2.0">
+            <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
+            <endpoint-config name="Standard-Endpoint-Config"/>
+            <endpoint-config name="Recording-Endpoint-Config">
+                <pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
+                    <handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
+                </pre-handler-chain>
+            </endpoint-config>
+            <client-config name="Standard-Client-Config"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:weld:4.0"/>
+    </profile>
+    <interfaces>
+        <interface name="management">
+            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+        </interface>
+        <interface name="public">
+            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+        </interface>
+    </interfaces>
+    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
+        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
+        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
+        <socket-binding name="http" port="${jboss.http.port:8080}"/>
+        <socket-binding name="https" port="${jboss.https.port:8443}"/>
+        <socket-binding name="txn-recovery-environment" port="4712"/>
+        <socket-binding name="txn-status-manager" port="4713"/>
+        <outbound-socket-binding name="mail-smtp">
+            <remote-destination host="localhost" port="25"/>
+        </outbound-socket-binding>
+    </socket-binding-group>
+</server>
\ No newline at end of file
diff --git a/elytron/wildfly-config.xml b/elytron/wildfly-config.xml
new file mode 100644
index 0000000..7fcf544
--- /dev/null
+++ b/elytron/wildfly-config.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2016 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration>
+    <authentication-client xmlns="urn:elytron:1.0">
+        <authentication-rules>
+            <rule use-configuration="default">
+                <match-host name="localhost"/>
+                <match-port number="9990"/>
+            </rule>
+        </authentication-rules>
+        <!--<ssl-context-rules>-->
+            <!--<rule use-ssl-context="oauth2-authorization-server-ssl">-->
+                <!--<match-host name="localhost"/>-->
+                <!--<match-port number="8543"/>-->
+            <!--</rule>-->
+        <!--</ssl-context-rules>-->
+        <!--<ssl-contexts>-->
+            <!--<ssl-context name="oauth2-authorization-server-ssl">-->
+                <!--<key-store-ssl-certificate key-store-name="default-keystore" alias="server"/>-->
+            <!--</ssl-context>-->
+        <!--</ssl-contexts>-->
+        <!--<key-stores>-->
+            <!--<key-store name="default-keystore" type="JKS">-->
+                <!--<file name="/pedroigor/development/workspace/jboss/keycloak/keycloak/distribution/demo-dist/target/keycloak-demo-3.1.0.CR1-SNAPSHOT/keycloak/standalone/configuration/application.truststore"/>-->
+                <!--<key-store-clear-password password="password"/>-->
+            <!--</key-store>-->
+        <!--</key-stores>-->
+        <authentication-configurations>
+            <configuration name="default">
+                <credentials>
+                    <oauth2-bearer-token token-endpoint-uri="http://localhost:8180/auth/realms/wildfly/protocol/openid-connect/token">
+                        <client-credentials client-id="wildfly-cli" client-secret="826e2750-dd70-4ff8-8fd0-05f6b2e871d1"/>
+                    </oauth2-bearer-token>
+                </credentials>
+                <allow-sasl-mechanisms names="JBOSS-LOCAL-USER EXTERNAL DIGEST-MD5 PLAIN ANONYMOUS OAUTHBEARER"/>
+                <set-mechanism-properties>
+                    <property key="wildfly.sasl.local-user.quiet-auth" value="true"/>
+                </set-mechanism-properties>
+                <use-service-loader-providers/>
+            </configuration>
+            <configuration name="using-client-credentials-from-callback-handler">
+                <credentials>
+                    <oauth2-bearer-token token-endpoint-uri="http://localhost:8180/auth/realms/wildfly/protocol/openid-connect/token"/>
+                </credentials>
+                <allow-sasl-mechanisms names="JBOSS-LOCAL-USER EXTERNAL DIGEST-MD5 PLAIN ANONYMOUS OAUTHBEARER"/>
+                <set-mechanism-properties>
+                    <property key="wildfly.sasl.local-user.quiet-auth" value="true"/>
+                </set-mechanism-properties>
+                <use-service-loader-providers/>
+            </configuration>
+        </authentication-configurations>
+    </authentication-client>
+</configuration>

pom.xml 22(+22 -0)

diff --git a/pom.xml b/pom.xml
index e545c8e..deb92ab 100755
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,8 @@
         <eap.version>7.0.0.Beta</eap.version>
         <jboss.as.version>7.2.0.Final</jboss.as.version>
         <wildfly.version>10.0.0.Final</wildfly.version>
+        <version.org.wildfly.security.wildfly-elytron>1.1.0.Beta32</version.org.wildfly.security.wildfly-elytron>
+        <version.org.wildfly.security.elytron-web.undertow-server>1.0.0.Beta14</version.org.wildfly.security.elytron-web.undertow-server>
 
         <aesh.version>0.66.12</aesh.version>
         <apache.httpcomponents.version>4.5</apache.httpcomponents.version>
@@ -622,6 +624,16 @@
                 <version>${wildfly.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.wildfly.security</groupId>
+                <artifactId>wildfly-elytron</artifactId>
+                <version>${version.org.wildfly.security.wildfly-elytron}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.security.elytron-web</groupId>
+                <artifactId>undertow-server</artifactId>
+                <version>${version.org.wildfly.security.elytron-web.undertow-server}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.infinispan</groupId>
                 <artifactId>infinispan-core</artifactId>
                 <version>${infinispan.version}</version>
@@ -923,6 +935,16 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wildfly-elytron-oidc-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-saml-wildfly-elytron-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
                 <artifactId>keycloak-wildfly-adduser</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/common/configure-elytron.xsl b/testsuite/integration-arquillian/servers/app-server/jboss/common/configure-elytron.xsl
new file mode 100644
index 0000000..96edcfe
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/common/configure-elytron.xsl
@@ -0,0 +1,90 @@
+<!--
+  ~ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ * and other contributors as indicated by the @author tags.
+  ~ *
+  ~ * Licensed under the Apache License, Version 2.0 (the "License");
+  ~ * you may not use this file except in compliance with the License.
+  ~ * You may obtain a copy of the License at
+  ~ *
+  ~ * http://www.apache.org/licenses/LICENSE-2.0
+  ~ *
+  ~ * Unless required by applicable law or agreed to in writing, software
+  ~ * distributed under the License is distributed on an "AS IS" BASIS,
+  ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ * See the License for the specific language governing permissions and
+  ~ * limitations under the License.
+  -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+    <xsl:variable name="undertowNamespace" select="'urn:jboss:domain:undertow:'"/>
+    <xsl:variable name="elytronNamespace" select="'urn:wildfly:elytron:'"/>
+    <xsl:variable name="securityNamespace" select="'urn:jboss:domain:security:'"/>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $elytronNamespace)]/*[local-name()='security-realms']">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | *"/>
+            <custom-realm name="KeycloakSAMLRealm" module="org.keycloak.keycloak-saml-wildfly-elytron-adapter" class-name="org.keycloak.adapters.saml.elytron.KeycloakSecurityRealm"/>
+            <custom-realm name="KeycloakOIDCRealm" module="org.keycloak.keycloak-wildfly-elytron-oidc-adapter" class-name="org.keycloak.adapters.elytron.KeycloakSecurityRealm"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $elytronNamespace)]/*[local-name()='security-domains']">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | *"/>
+            <security-domain name="KeycloakDomain" default-realm="KeycloakOIDCRealm" permission-mapper="default-permission-mapper" security-event-listener="local-audit">
+                <realm name="KeycloakOIDCRealm"/>
+                <realm name="KeycloakSAMLRealm"/>
+            </security-domain>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $elytronNamespace)]/*[local-name()='mappers']">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | *"/>
+            <constant-realm-mapper name="keycloak-saml-realm-mapper" realm-name="KeycloakSAMLRealm"/>
+            <constant-realm-mapper name="keycloak-oidc-realm-mapper" realm-name="KeycloakOIDCRealm"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $elytronNamespace)]/*[local-name()='http']">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | *"/>
+            <http-authentication-factory name="keycloak-http-authentication" http-server-mechanism-factory="keycloak-http-server-mechanism-factory" security-domain="KeycloakDomain">
+                <mechanism-configuration>
+                    <mechanism mechanism-name="KEYCLOAK">
+                        <mechanism-realm realm-name="KeycloakOIDCRealm" realm-mapper="keycloak-oidc-realm-mapper"/>
+                    </mechanism>
+                    <mechanism mechanism-name="KEYCLOAK-SAML">
+                        <mechanism-realm realm-name="KeycloakSAMLRealm" realm-mapper="keycloak-saml-realm-mapper"/>
+                    </mechanism>
+                </mechanism-configuration>
+            </http-authentication-factory>
+            <service-loader-http-server-mechanism-factory name="keycloak-oidc-http-server-mechanism-factory" module="org.keycloak.keycloak-wildfly-elytron-oidc-adapter"/>
+            <service-loader-http-server-mechanism-factory name="keycloak-saml-http-server-mechanism-factory" module="org.keycloak.keycloak-saml-wildfly-elytron-adapter"/>
+            <aggregate-http-server-mechanism-factory name="keycloak-http-server-mechanism-factory">
+                <http-server-mechanism-factory name="keycloak-oidc-http-server-mechanism-factory"/>
+                <http-server-mechanism-factory name="keycloak-saml-http-server-mechanism-factory"/>
+            </aggregate-http-server-mechanism-factory>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $undertowNamespace)]">
+        <xsl:copy>
+            <xsl:apply-templates select="@* | *"/>
+            <application-security-domains>
+                <application-security-domain name="other" http-authentication-factory="keycloak-http-authentication"/>
+            </application-security-domains>
+        </xsl:copy>
+    </xsl:template>
+
+    <!-- Need to remove the legacy security-domain otherwise Elytron will not be enabled to deployments -->
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $securityNamespace)]/*[local-name()='security-domains']/*[local-name()='security-domain'][@name='keycloak']"/>
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()"/>
+        </xsl:copy>
+    </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml
index 658fb39..90a3952 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml
@@ -444,6 +444,45 @@
                 <module>eap6-fuse</module>
             </modules>
         </profile>
+
+        <profile>
+            <id>app-server-wildfly-elytron</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <properties>
+                <wildfly.version>${elytron.wildfly.version}</wildfly.version>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>xml-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>configure-adapter-debug-log</id>
+                                <phase>process-test-resources</phase>
+                                <goals>
+                                    <goal>transform</goal>
+                                </goals>
+                                <configuration>
+                                    <transformationSets>
+                                        <transformationSet>
+                                            <dir>${app.server.jboss.home}/standalone/configuration</dir>
+                                            <includes>
+                                                <include>standalone.xml</include>
+                                            </includes>
+                                            <stylesheet>${common.resources}/configure-elytron.xsl</stylesheet>
+                                            <outputDir>${app.server.jboss.home}/standalone/configuration</outputDir>
+                                        </transformationSet>
+                                    </transformationSets>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
     </profiles>    
 
 </project>