keycloak-aplcache

Changes

examples/as7-eap-demo/server/src/main/webapp/saas/css/base.css 35(+0 -35)

examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.css 321(+0 -321)

examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.less 393(+0 -393)

examples/as7-eap-demo/server/src/main/webapp/saas/css/forms.css 61(+0 -61)

examples/as7-eap-demo/server/src/main/webapp/saas/css/forms.less 66(+0 -66)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/btn-social-fb.svg 8(+0 -8)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.svg 164(+0 -164)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separator.svg 7(+0 -7)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separators.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.svg 19(+0 -19)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-screen-background.jpg 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/img/register-login-bg.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/login-screen.css 268(+0 -268)

examples/as7-eap-demo/server/src/main/webapp/saas/css/login-screen.less 302(+0 -302)

examples/as7-eap-demo/server/src/main/webapp/saas/css/reset.css 71(+0 -71)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial.css 473(+0 -473)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial.less 281(+0 -281)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.svg 151(+0 -151)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/img/red-hat-logo.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/img/subway-logo.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login1.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login2.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/bootstrap/css/bootstrap.css 6158(+0 -6158)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/css/font-awesome.css 540(+0 -540)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/css/font-awesome.min.css 33(+0 -33)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/css/font-awesome-ie7.min.css 22(+0 -22)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/font/FontAwesome.otf 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/font/fontawesome-webfont.eot 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/font/fontawesome-webfont.svg 284(+0 -284)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/font/fontawesome-webfont.ttf 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/lib/font-awesome/font/fontawesome-webfont.woff 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/oauthGrantForm.jsp 87(+0 -87)

examples/as7-eap-demo/server/src/main/webapp/saas/securityFailure.jsp 23(+0 -23)

Details

diff --git a/core/src/main/java/org/keycloak/adapters/AdapterAdminResourceConstants.java b/core/src/main/java/org/keycloak/adapters/AdapterAdminResourceConstants.java
new file mode 100755
index 0000000..7c0bb87
--- /dev/null
+++ b/core/src/main/java/org/keycloak/adapters/AdapterAdminResourceConstants.java
@@ -0,0 +1,9 @@
+package org.keycloak.adapters;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AdapterAdminResourceConstants {
+    public static final String LOGOUT = "k_logout";
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
index dfd08ad..904b692 100755
--- a/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/PublishedRealmRepresentation.java
@@ -3,7 +3,7 @@ package org.keycloak.representations.idm;
 import org.bouncycastle.openssl.PEMWriter;
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
-import org.keycloak.PemUtils;
+import org.keycloak.util.PemUtils;
 
 import java.io.IOException;
 import java.io.StringWriter;
diff --git a/core/src/main/java/org/keycloak/representations/SkeletonKeyToken.java b/core/src/main/java/org/keycloak/representations/SkeletonKeyToken.java
index 0f4fe1b..a0c6968 100755
--- a/core/src/main/java/org/keycloak/representations/SkeletonKeyToken.java
+++ b/core/src/main/java/org/keycloak/representations/SkeletonKeyToken.java
@@ -2,7 +2,6 @@ package org.keycloak.representations;
 
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
-import org.keycloak.jwt.JsonWebToken;
 
 import java.util.HashMap;
 import java.util.HashSet;
diff --git a/core/src/main/java/org/keycloak/SkeletonKeySession.java b/core/src/main/java/org/keycloak/SkeletonKeySession.java
index 3f10c7e..83e87e9 100755
--- a/core/src/main/java/org/keycloak/SkeletonKeySession.java
+++ b/core/src/main/java/org/keycloak/SkeletonKeySession.java
@@ -1,5 +1,6 @@
 package org.keycloak;
 
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.representations.SkeletonKeyToken;
 
 import java.io.Serializable;
diff --git a/core/src/main/java/org/keycloak/util/StreamUtil.java b/core/src/main/java/org/keycloak/util/StreamUtil.java
new file mode 100755
index 0000000..428a590
--- /dev/null
+++ b/core/src/main/java/org/keycloak/util/StreamUtil.java
@@ -0,0 +1,31 @@
+package org.keycloak.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class StreamUtil {
+    public static String readString(InputStream in) throws IOException
+    {
+        char[] buffer = new char[1024];
+        StringBuilder builder = new StringBuilder();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+        int wasRead = 0;
+        do
+        {
+            wasRead = reader.read(buffer, 0, 1024);
+            if (wasRead > 0)
+            {
+                builder.append(buffer, 0, wasRead);
+            }
+        }
+        while (wasRead > -1);
+
+        return builder.toString();
+    }
+}
diff --git a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
index fca38a9..7b45c2b 100755
--- a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
+++ b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json
@@ -63,7 +63,7 @@
         {
             "name": "customer-portal",
             "enabled": true,
-            "adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
+            "adminUrl": "http://localhost:8080/customer-portal",
             "credentials": [
                 {
                     "type": "password",
@@ -74,7 +74,7 @@
         {
             "name": "product-portal",
             "enabled": true,
-            "adminUrl": "http://localhost:8080/product-portal/j_admin_request",
+            "adminUrl": "http://localhost:8080/product-portal",
             "credentials": [
                 {
                     "type": "password",
diff --git a/examples/wildfly-demo/server/src/main/resources/META-INF/testrealm.json b/examples/wildfly-demo/server/src/main/resources/META-INF/testrealm.json
index fca38a9..7b45c2b 100755
--- a/examples/wildfly-demo/server/src/main/resources/META-INF/testrealm.json
+++ b/examples/wildfly-demo/server/src/main/resources/META-INF/testrealm.json
@@ -63,7 +63,7 @@
         {
             "name": "customer-portal",
             "enabled": true,
-            "adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
+            "adminUrl": "http://localhost:8080/customer-portal",
             "credentials": [
                 {
                     "type": "password",
@@ -74,7 +74,7 @@
         {
             "name": "product-portal",
             "enabled": true,
-            "adminUrl": "http://localhost:8080/product-portal/j_admin_request",
+            "adminUrl": "http://localhost:8080/product-portal",
             "credentials": [
                 {
                     "type": "password",
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java
index b0db3dc..1b4245f 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java
@@ -2,10 +2,10 @@ package org.keycloak.adapters.config;
 
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
-import org.keycloak.EnvUtil;
-import org.keycloak.PemUtils;
-import org.keycloak.ResourceMetadata;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.util.EnvUtil;
+import org.keycloak.util.PemUtils;
+import org.keycloak.adapters.ResourceMetadata;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java
index 2e5e06d..fe4cf3a 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java
@@ -1,7 +1,7 @@
 package org.keycloak.adapters.config;
 
 import org.apache.http.client.HttpClient;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.util.KeycloakUriBuilder;
 
 import java.util.HashMap;
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/TokenGrantRequest.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/TokenGrantRequest.java
index 469ab06..76fdf4b 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/TokenGrantRequest.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/TokenGrantRequest.java
@@ -12,11 +12,10 @@ import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.util.JsonSerialization;
 import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.StreamUtil;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -89,32 +88,12 @@ public class TokenGrantRequest {
     }
 
 
-    protected static String readString(InputStream in) throws IOException
-    {
-        char[] buffer = new char[1024];
-        StringBuilder builder = new StringBuilder();
-        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-        int wasRead = 0;
-        do
-        {
-            wasRead = reader.read(buffer, 0, 1024);
-            if (wasRead > 0)
-            {
-                builder.append(buffer, 0, wasRead);
-            }
-        }
-        while (wasRead > -1);
-
-        return builder.toString();
-    }
-
-
     protected static void error(int status, HttpEntity entity) throws HttpFailure, IOException {
        String body = null;
         if (entity != null) {
             InputStream is = entity.getContent();
             try {
-                body = readString(is);
+                body = StreamUtil.readString(is);
             } catch (IOException e) {
 
             } finally {
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java
index 823b703..8c7f992 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java
@@ -8,7 +8,7 @@ import org.apache.catalina.connector.Response;
 import org.apache.catalina.valves.ValveBase;
 import org.jboss.logging.Logger;
 import org.keycloak.SkeletonKeySession;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.SkeletonKeyToken;
 
 import javax.management.ObjectName;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/BearerTokenAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/BearerTokenAuthenticatorValve.java
index e6afc26..4cececc 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/BearerTokenAuthenticatorValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/BearerTokenAuthenticatorValve.java
@@ -10,10 +10,9 @@ import org.apache.catalina.connector.Response;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.deploy.LoginConfig;
 import org.jboss.logging.Logger;
-import org.keycloak.ResourceMetadata;
-import org.keycloak.SkeletonKeySession;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.adapters.config.AdapterConfigLoader;
 
 import javax.security.auth.login.LoginException;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
index f289a02..da95481 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
@@ -3,7 +3,7 @@ package org.keycloak.adapters.as7;
 import org.apache.catalina.connector.Request;
 import org.jboss.logging.Logger;
 import org.keycloak.RSATokenVerifier;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.SkeletonKeyPrincipal;
 import org.keycloak.SkeletonKeySession;
 import org.keycloak.VerificationException;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java
index 5c323d8..e70dbda 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java
@@ -3,7 +3,7 @@ package org.keycloak.adapters.as7;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.jboss.logging.Logger;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
index 46717d2..b8b0688 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
@@ -13,21 +13,24 @@ import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.deploy.LoginConfig;
 import org.apache.catalina.realm.GenericPrincipal;
 import org.jboss.logging.Logger;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.AdapterAdminResourceConstants;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.SkeletonKeyPrincipal;
 import org.keycloak.SkeletonKeySession;
 import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.adapters.config.RealmConfiguration;
 import org.keycloak.adapters.config.RealmConfigurationLoader;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
 import org.keycloak.representations.SkeletonKeyToken;
-import org.keycloak.representations.idm.admin.LogoutAction;
+import org.keycloak.representations.adapters.action.LogoutAction;
 import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.StreamUtil;
 
 import javax.security.auth.login.LoginException;
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.HashSet;
@@ -80,8 +83,12 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
                 return;
             }
             String requestURI = request.getDecodedRequestURI();
-            if (requestURI.endsWith("j_admin_request")) {
-                adminRequest(request, response);
+            if (requestURI.endsWith(AdapterAdminResourceConstants.LOGOUT)) {
+                JWSInput input = verifyAdminRequest(request, response);
+                if (input == null) {
+                    return; // we failed to verify the request
+                }
+                remoteLogout(input, response);
                 return;
             }
             super.invoke(request, response);
@@ -115,12 +122,12 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
         return false;
     }
 
-    protected void adminRequest(Request request, HttpServletResponse response) throws IOException {
-        String token = request.getParameter("token");
+    protected JWSInput verifyAdminRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String token = StreamUtil.readString(request.getInputStream());
         if (token == null) {
             log.warn("admin request failed, no token");
             response.sendError(403, "no token");
-            return;
+            return null;
         }
 
         JWSInput input = new JWSInput(token);
@@ -132,15 +139,9 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
         if (!verified) {
             log.warn("admin request failed, unable to verify token");
             response.sendError(403, "verification failed");
-            return;
-        }
-        String action = request.getParameter("action");
-        if (LogoutAction.LOGOUT_ACTION.equals(action)) {
-            remoteLogout(input, response);
-        } else {
-            log.warn("admin request failed, unknown action");
-            response.sendError(403, "Unknown action");
+            return null;
         }
+        return input;
     }
 
     protected void remoteLogout(JWSInput token, HttpServletResponse response) throws IOException {
@@ -152,11 +153,6 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
                 response.sendError(400, "Expired token");
                 return;
             }
-            if (!LogoutAction.LOGOUT_ACTION.equals(action.getAction())) {
-                log.warn("Action doesn't match");
-                response.sendError(400, "Action does not match");
-                return;
-            }
             if (!resourceMetadata.getResourceName().equals(action.getResource())) {
                 log.warn("Resource name does not match");
                 response.sendError(400, "Resource name does not match");
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
index b42794e..319b5ac 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
@@ -3,7 +3,7 @@ package org.keycloak.jaxrs;
 import org.jboss.resteasy.logging.Logger;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.RSATokenVerifier;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.SkeletonKeyPrincipal;
 import org.keycloak.SkeletonKeySession;
 import org.keycloak.VerificationException;
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java
index e294a2e..850b578 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java
@@ -5,7 +5,7 @@ import io.undertow.server.HttpServerExchange;
 import io.undertow.util.Headers;
 import org.jboss.logging.Logger;
 import org.keycloak.SkeletonKeySession;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.SkeletonKeyToken;
 
 import javax.servlet.ServletException;
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java
index cce080c..978b382 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java
@@ -5,11 +5,10 @@ import io.undertow.security.api.SecurityContext;
 import io.undertow.server.HttpServerExchange;
 import org.jboss.logging.Logger;
 import org.keycloak.RSATokenVerifier;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.VerificationException;
 import org.keycloak.representations.SkeletonKeyToken;
 
-import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.security.cert.X509Certificate;
 import java.util.HashSet;
 import java.util.List;
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
index 69981bd..120546f 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
@@ -7,10 +7,10 @@ import io.undertow.server.HttpServerExchange;
 import io.undertow.util.AttachmentKey;
 import org.jboss.logging.Logger;
 import org.keycloak.adapters.config.RealmConfiguration;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.SkeletonKeyPrincipal;
 import org.keycloak.SkeletonKeySession;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.SkeletonKeyToken;
 
 import java.security.Principal;
@@ -32,16 +32,21 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
     protected RealmConfiguration realmConfig;
     protected int sslRedirectPort;
 
-    public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig, int sslRedirectPort) {
-        this.resourceMetadata = resourceMetadata;
+    public KeycloakAuthenticationMechanism(AdapterConfig config, RealmConfiguration realmConfig, int sslRedirectPort) {
+        this.resourceMetadata = realmConfig.getMetadata();
         this.adapterConfig = config;
         this.realmConfig = realmConfig;
         this.sslRedirectPort = sslRedirectPort;
     }
 
-    public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig) {
+    public KeycloakAuthenticationMechanism(AdapterConfig adapterConfig, ResourceMetadata resourceMetadata) {
         this.resourceMetadata = resourceMetadata;
-        this.adapterConfig = config;
+        this.adapterConfig = adapterConfig;
+    }
+
+    public KeycloakAuthenticationMechanism(AdapterConfig adapterConfig, RealmConfiguration realmConfig) {
+        this.resourceMetadata = realmConfig.getMetadata();
+        this.adapterConfig = adapterConfig;
         this.realmConfig = realmConfig;
     }
 
@@ -57,8 +62,8 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
             final SkeletonKeyToken token = bearer.getToken();
             String surrogate = bearer.getSurrogate();
             SkeletonKeySession session = new SkeletonKeySession(bearer.getTokenString(), token, resourceMetadata);
-            propagateBearer(exchange, session);
-            completeAuthentication(exchange, securityContext, token, surrogate);
+            SkeletonKeyPrincipal principal = completeAuthentication(securityContext, token, surrogate);
+            propagateBearer(exchange, session, principal);
             return AuthenticationMechanismOutcome.AUTHENTICATED;
         }
         else if (adapterConfig.isBearerOnly()) {
@@ -78,8 +83,8 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
 
         }
         SkeletonKeySession session = new SkeletonKeySession(oauth.getTokenString(), oauth.getToken(), resourceMetadata);
-        propagateOauth(exchange, session);
-        completeAuthentication(exchange, securityContext, oauth.getToken(), null);
+        SkeletonKeyPrincipal principal = completeAuthentication(securityContext, oauth.getToken(), null);
+        propagateOauth(exchange, session, principal);
         log.info("AUTHENTICATED");
         return AuthenticationMechanismOutcome.AUTHENTICATED;
     }
@@ -92,7 +97,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
         return new BearerTokenAuthenticator(resourceMetadata, adapterConfig.isUseResourceRoleMappings());
     }
 
-    protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, SkeletonKeyToken token, String surrogate) {
+    protected SkeletonKeyPrincipal completeAuthentication(SecurityContext securityContext, SkeletonKeyToken token, String surrogate) {
         final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
         Set<String> roles = null;
         if (adapterConfig.isUseResourceRoleMappings()) {
@@ -116,14 +121,15 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism 
             }
         };
         securityContext.authenticationComplete(account, "KEYCLOAK", true);
+        return skeletonKeyPrincipal;
     }
 
-    protected void propagateBearer(HttpServerExchange exchange, SkeletonKeySession session) {
+    protected void propagateBearer(HttpServerExchange exchange, SkeletonKeySession session, SkeletonKeyPrincipal principal) {
         exchange.putAttachment(SKELETON_KEY_SESSION_ATTACHMENT_KEY, session);
 
     }
 
-    protected void propagateOauth(HttpServerExchange exchange, SkeletonKeySession session) {
+    protected void propagateOauth(HttpServerExchange exchange, SkeletonKeySession session, SkeletonKeyPrincipal principal) {
         exchange.putAttachment(SKELETON_KEY_SESSION_ATTACHMENT_KEY, session);
     }
 
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
index 7a39424..52eb239 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
@@ -12,7 +12,8 @@ import io.undertow.servlet.api.DeploymentInfo;
 import io.undertow.servlet.api.LoginConfig;
 import io.undertow.servlet.api.ServletSessionConfig;
 import org.jboss.logging.Logger;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.adapters.config.RealmConfiguration;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.adapters.config.RealmConfigurationLoader;
 
 import javax.servlet.ServletContext;
@@ -52,20 +53,30 @@ public class KeycloakServletExtension implements ServletExtension {
         RealmConfigurationLoader loader = new RealmConfigurationLoader(is);
         loader.init(true);
         AdapterConfig keycloakConfig = loader.getAdapterConfig();
+        RealmConfiguration realmConfiguration = loader.getRealmConfiguration();
         PreflightCorsHandler.Wrapper preflight = new PreflightCorsHandler.Wrapper(keycloakConfig);
-        final ServletKeycloakAuthenticationMechanism auth = new ServletKeycloakAuthenticationMechanism(loader.getResourceMetadata(),
+        UserSessionManagement userSessionManagement = new UserSessionManagement(realmConfiguration);
+        ServletKeycloakAuthenticationMechanism auth = null;
+        if (keycloakConfig.isBearerOnly()) {
+            auth = new ServletKeycloakAuthenticationMechanism(keycloakConfig, loader.getResourceMetadata(), deploymentInfo.getConfidentialPortManager());
+        } else {
+            auth = new ServletKeycloakAuthenticationMechanism(
+                userSessionManagement,
                 keycloakConfig,
-                loader.getRealmConfiguration(),
+                realmConfiguration,
                 deploymentInfo.getConfidentialPortManager());
+        }
         ServletAuthenticatedActionsHandler.Wrapper actions = new ServletAuthenticatedActionsHandler.Wrapper(keycloakConfig);
 
         // setup handlers
 
         deploymentInfo.addInitialHandlerChainWrapper(preflight); // cors preflight
+        deploymentInfo.addOuterHandlerChainWrapper(new ServletAdminActionsHandler.Wrapper(realmConfiguration, userSessionManagement));
+        final ServletKeycloakAuthenticationMechanism theAuth = auth;
         deploymentInfo.addAuthenticationMechanism("KEYCLOAK", new AuthenticationMechanismFactory() {
             @Override
             public AuthenticationMechanism create(String s, FormParserFactory formParserFactory, Map<String, String> stringStringMap) {
-                return auth;
+                return theAuth;
             }
         }); // authentication
         deploymentInfo.addInnerHandlerChainWrapper(ServletPropagateSessionHandler.WRAPPER); // propagates SkeletonKeySession
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java
index f56af73..0bc53b7 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java
@@ -5,7 +5,7 @@ import io.undertow.server.HttpHandler;
 import io.undertow.server.HttpServerExchange;
 import io.undertow.util.HttpString;
 import org.jboss.logging.Logger;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java
new file mode 100755
index 0000000..4bfacca
--- /dev/null
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java
@@ -0,0 +1,95 @@
+package org.keycloak.adapters.undertow;
+
+import io.undertow.server.HandlerWrapper;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.SessionManager;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterAdminResourceConstants;
+import org.keycloak.adapters.config.RealmConfiguration;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.util.StreamUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ServletAdminActionsHandler implements HttpHandler {
+
+    private static final Logger log = Logger.getLogger(ServletAdminActionsHandler.class);
+    protected HttpHandler next;
+    protected UserSessionManagement userSessionManagement;
+    protected RealmConfiguration realmConfig;
+
+    public static class Wrapper implements HandlerWrapper {
+        protected RealmConfiguration realmConfig;
+        protected UserSessionManagement userSessionManagement;
+
+        public Wrapper(RealmConfiguration realmConfig, UserSessionManagement userSessionManagement) {
+            this.realmConfig = realmConfig;
+            this.userSessionManagement = userSessionManagement;
+        }
+
+        @Override
+        public HttpHandler wrap(HttpHandler handler) {
+            return new ServletAdminActionsHandler(realmConfig, userSessionManagement, handler);
+        }
+    }
+
+    protected ServletAdminActionsHandler(RealmConfiguration realmConfig,
+                                         UserSessionManagement userSessionManagement,
+                                         HttpHandler next) {
+        this.next = next;
+        this.userSessionManagement = userSessionManagement;
+        this.realmConfig = realmConfig;
+    }
+
+    protected JWSInput verifyAdminRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        String token = StreamUtil.readString(request.getInputStream());
+        if (token == null) {
+            log.warn("admin request failed, no token");
+            response.sendError(403, "no token");
+            return null;
+        }
+
+        JWSInput input = new JWSInput(token);
+        boolean verified = false;
+        try {
+            verified = RSAProvider.verify(input, realmConfig.getMetadata().getRealmKey());
+        } catch (Exception ignore) {
+        }
+        if (!verified) {
+            log.warn("admin request failed, unable to verify token");
+            response.sendError(403, "verification failed");
+            return null;
+        }
+        return input;
+    }
+
+
+
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        log.debugv("adminActions {0}", exchange.getRequestURI());
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        HttpServletRequest request = (HttpServletRequest) servletRequestContext.getServletRequest();
+        HttpServletResponse response = (HttpServletResponse) servletRequestContext.getServletResponse();
+        SessionManager manager = servletRequestContext.getDeployment().getSessionManager();
+        String requestUri = exchange.getRequestURI();
+        if (requestUri.endsWith(AdapterAdminResourceConstants.LOGOUT)) {
+            JWSInput token = verifyAdminRequest(request, response);
+            if (token == null) return;
+            userSessionManagement.remoteLogout(token, manager, response);
+            return;
+        } else {
+            next.handleRequest(exchange);
+            return;
+        }
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAuthenticatedActionsHandler.java
index d724d46..63eea05 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAuthenticatedActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAuthenticatedActionsHandler.java
@@ -5,7 +5,7 @@ import io.undertow.server.HttpHandler;
 import io.undertow.server.HttpServerExchange;
 import io.undertow.servlet.handlers.ServletRequestContext;
 import org.keycloak.SkeletonKeySession;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java
index 4c504c2..89f8719 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java
@@ -3,10 +3,11 @@ package org.keycloak.adapters.undertow;
 import io.undertow.server.HttpServerExchange;
 import io.undertow.servlet.api.ConfidentialPortManager;
 import io.undertow.servlet.handlers.ServletRequestContext;
+import org.keycloak.SkeletonKeyPrincipal;
 import org.keycloak.adapters.config.RealmConfiguration;
-import org.keycloak.ResourceMetadata;
+import org.keycloak.adapters.ResourceMetadata;
 import org.keycloak.SkeletonKeySession;
-import org.keycloak.representations.config.AdapterConfig;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
@@ -17,32 +18,42 @@ import javax.servlet.http.HttpSession;
  */
 public class ServletKeycloakAuthenticationMechanism extends KeycloakAuthenticationMechanism {
     protected ConfidentialPortManager portManager;
+    protected UserSessionManagement userSessionManagement;
 
-    public ServletKeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig, ConfidentialPortManager portManager) {
-        super(resourceMetadata, config, realmConfig);
+    public ServletKeycloakAuthenticationMechanism(UserSessionManagement userSessionManagement, AdapterConfig config, RealmConfiguration realmConfig, ConfidentialPortManager portManager) {
+        super(config, realmConfig);
         this.portManager = portManager;
+        this.userSessionManagement = userSessionManagement;
     }
 
+    public ServletKeycloakAuthenticationMechanism(AdapterConfig config, ResourceMetadata metadata, ConfidentialPortManager portManager) {
+        super(config, metadata);
+        this.portManager = portManager;
+        this.userSessionManagement = userSessionManagement;
+    }
+
+
     @Override
     protected OAuthAuthenticator createOAuthAuthenticator(HttpServerExchange exchange) {
         return new ServletOAuthAuthenticator(exchange, realmConfig, portManager);
     }
 
     @Override
-    protected void propagateBearer(HttpServerExchange exchange, SkeletonKeySession session) {
-        super.propagateBearer(exchange, session);
+    protected void propagateBearer(HttpServerExchange exchange, SkeletonKeySession skSession, SkeletonKeyPrincipal principal) {
+        super.propagateBearer(exchange, skSession, principal);
         final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
         HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
-        req.setAttribute(SkeletonKeySession.class.getName(), session);
+        req.setAttribute(SkeletonKeySession.class.getName(), skSession);
     }
 
     @Override
-    protected void propagateOauth(HttpServerExchange exchange, SkeletonKeySession skSession) {
-        super.propagateOauth(exchange, skSession);
+    protected void propagateOauth(HttpServerExchange exchange, SkeletonKeySession skSession, SkeletonKeyPrincipal principal) {
+        super.propagateBearer(exchange, skSession, principal);
         final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
         HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
         req.setAttribute(SkeletonKeySession.class.getName(), skSession);
         HttpSession session = req.getSession(true);
         session.setAttribute(SkeletonKeySession.class.getName(), skSession);
+        userSessionManagement.login(servletRequestContext.getDeployment().getSessionManager(), session, principal.getName());
     }
 }
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java
new file mode 100755
index 0000000..0cc1b8b
--- /dev/null
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java
@@ -0,0 +1,188 @@
+package org.keycloak.adapters.undertow;
+
+import io.undertow.security.api.AuthenticatedSessionManager;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.Session;
+import io.undertow.server.session.SessionListener;
+import io.undertow.server.session.SessionManager;
+import io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler;
+import org.jboss.logging.Logger;
+import org.keycloak.SkeletonKeySession;
+import org.keycloak.adapters.config.RealmConfiguration;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.representations.adapters.action.LogoutAction;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.StreamUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Manages relationship to users and sessions so that forced admin logout can be implemented
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserSessionManagement implements SessionListener {
+    private static final Logger log = Logger.getLogger(UserSessionManagement.class);
+    private static final String AUTH_SESSION_NAME = CachedAuthenticatedSessionHandler.class.getName() + ".AuthenticatedSession";
+    protected ConcurrentHashMap<String, Set<String>> userSessionMap = new ConcurrentHashMap<String, Set<String>>();
+
+    protected RealmConfiguration realmInfo;
+
+    public UserSessionManagement(RealmConfiguration realmInfo) {
+        this.realmInfo = realmInfo;
+    }
+
+    public void remoteLogout(JWSInput token, SessionManager manager, HttpServletResponse response) throws IOException {
+        try {
+            log.debug("->> remoteLogout: ");
+            LogoutAction action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
+            if (action.isExpired()) {
+                log.warn("admin request failed, expired token");
+                response.sendError(400, "Expired token");
+                return;
+            }
+            if (!realmInfo.getMetadata().getResourceName().equals(action.getResource())) {
+                log.warn("Resource name does not match");
+                response.sendError(400, "Resource name does not match");
+                return;
+
+            }
+            String user = action.getUser();
+            if (user != null) {
+                log.debug("logout of session for: " + user);
+                logout(manager, user);
+            } else {
+                log.debug("logout of all sessions");
+                logoutAll(manager);
+            }
+        } catch (Exception e) {
+            log.warn("failed to logout", e);
+            response.sendError(500, "Failed to logout");
+        }
+        response.setStatus(204);
+    }
+
+    public void login(SessionManager manager, HttpSession session, String username) {
+        String sessionId = session.getId();
+        addAuthenticatedSession(username, sessionId);
+        manager.registerSessionListener(this);
+    }
+
+    protected void addAuthenticatedSession(String username, String sessionId) {
+        synchronized (userSessionMap) {
+            Set<String> map = userSessionMap.get(username);
+            if (map == null) {
+                final Set<String> value = new HashSet<String>();
+                map = userSessionMap.putIfAbsent(username, value);
+                if (map == null) {
+                    map = value;
+                }
+            }
+            synchronized (map) {
+                map.add(sessionId);
+            }
+
+        }
+    }
+
+    protected void removeAuthenticatedSession(String sessionId, String username) {
+        synchronized (userSessionMap) {
+            Set<String> map = userSessionMap.get(username);
+            if (map == null) return;
+            synchronized (map) {
+                map.remove(sessionId);
+                if (map.isEmpty()) userSessionMap.remove(username);
+            }
+        }
+    }
+
+    public void logoutAll(SessionManager manager) {
+        List<String> users = new ArrayList<String>();
+        users.addAll(userSessionMap.keySet());
+        for (String user : users) logout(manager, user);
+    }
+
+    public void logoutAllBut(SessionManager manager, String but) {
+        List<String> users = new ArrayList<String>();
+        users.addAll(userSessionMap.keySet());
+        for (String user : users) {
+            if (!but.equals(user)) logout(manager, user);
+        }
+    }
+
+    public void logout(SessionManager manager, String user) {
+        log.debug("logoutUser: " + user);
+        Set<String> map = userSessionMap.remove(user);
+        if (map == null) {
+            log.debug("no session for user: " + user);
+            return;
+        }
+        log.debug("found session for user");
+        synchronized (map) {
+            for (String id : map) {
+                log.debug("invalidating session for user: " + user);
+                Session session = manager.getSession(id);
+                try {
+                    session.invalidate(null);
+                } catch (Exception e) {
+                    log.warn("Session already invalidated.");
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public void sessionCreated(Session session, HttpServerExchange exchange) {
+    }
+
+    @Override
+    public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
+        // Look up the single session id associated with this session (if any)
+        String username = getUsernameFromSession(session);
+        if (username == null) return;
+        String sessionId = session.getId();
+        removeAuthenticatedSession(sessionId, username);
+    }
+
+    protected String getUsernameFromSession(Session session) {
+        AuthenticatedSessionManager.AuthenticatedSession authSession = (AuthenticatedSessionManager.AuthenticatedSession) session.getAttribute(AUTH_SESSION_NAME);
+        if (authSession == null) return null;
+        return authSession.getAccount().getPrincipal().getName();
+
+    }
+
+
+    @Override
+    public void sessionIdChanged(Session session, String oldSessionId) {
+        String username = getUsernameFromSession(session);
+        if (username == null) return;
+        removeAuthenticatedSession(oldSessionId, username);
+        addAuthenticatedSession(session.getId(), username);
+    }
+
+    @Override
+    public void attributeAdded(Session session, String name, Object value) {
+    }
+
+    @Override
+    public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) {
+    }
+
+    @Override
+    public void attributeRemoved(Session session, String name, Object oldValue) {
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index b6227cd..3427777 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1,7 +1,7 @@
 package org.keycloak.models.jpa;
 
 import org.bouncycastle.openssl.PEMWriter;
-import org.keycloak.PemUtils;
+import org.keycloak.util.PemUtils;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
index 0c8bfc4..637ee1c 100755
--- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
+++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java
@@ -1,7 +1,7 @@
 package org.keycloak.models.picketlink;
 
 import org.bouncycastle.openssl.PEMWriter;
-import org.keycloak.PemUtils;
+import org.keycloak.util.PemUtils;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.IdGenerator;
 import org.keycloak.models.KeycloakSession;
@@ -493,7 +493,7 @@ public class RealmAdapter implements RealmModel {
         } else if (cred.getType().equals(UserCredentialModel.CLIENT_CERT)) {
             X509Certificate cert = null;
             try {
-                cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
+                cert = PemUtils.decodeCertificate(cred.getValue());
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
index fd05120..27bb39e 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -7,8 +7,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.representations.config.AdapterConfig;
-import org.keycloak.representations.config.BaseAdapterConfig;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index cee3047..82f7ade 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -4,9 +4,10 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClient;
 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.TokenIdGenerator;
+import org.keycloak.adapters.AdapterAdminResourceConstants;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.RealmModel;
-import org.keycloak.representations.idm.admin.LogoutAction;
+import org.keycloak.representations.adapters.action.LogoutAction;
 
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Form;
@@ -41,10 +42,8 @@ public class ResourceAdminManager {
         if (managementUrl != null) {
             LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), System.currentTimeMillis() / 1000 + 30, resource.getName(), user);
             String token = new TokenManager().encodeToken(realm, adminAction);
-            Form form = new Form();
-            form.param("token", token);
             logger.debug("logout user: {0} resource: {1} url: {2}", user, resource.getName(), managementUrl);
-            Response response = client.target(managementUrl).queryParam("action", "logout").request().post(Entity.form(form));
+            Response response = client.target(managementUrl).path(AdapterAdminResourceConstants.LOGOUT).request().post(Entity.text(token));
             boolean success = response.getStatus() == 204;
             response.close();
             return success;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
index b65372c..66cc4b7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
@@ -1,14 +1,12 @@
 package org.keycloak.services.resources.admin;
 
-import org.codehaus.jackson.map.ObjectMapper;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
-import org.keycloak.representations.config.AdapterConfig;
-import org.keycloak.representations.config.BaseAdapterConfig;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.ApplicationManager;