From 82af7cbfa2dd640847ffe0128db4e9c19cd051ab Mon Sep 17 00:00:00 2001 From: mposolda Date: Fri, 31 Oct 2014 13:17:14 +0100 Subject: [PATCH] Fix multi-tenancy on EAP63/AS7 --- examples/multi-tenant/README.md | 2 +- .../adapters/as7/CatalinaCookieTokenStore.java | 11 ++++++----- .../as7/CatalinaSessionTokenStore.java | 18 ++++++++++-------- .../as7/KeycloakAuthenticatorValve.java | 4 ++-- .../tomcat7/CatalinaCookieTokenStore.java | 11 ++++++----- .../tomcat7/CatalinaSessionTokenStore.java | 18 ++++++++++-------- .../tomcat7/KeycloakAuthenticatorValve.java | 4 ++-- 7 files changed, 37 insertions(+), 31 deletions(-) diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md index 71c9b8c7eaa..8dd3c03bbb2 100644 --- a/examples/multi-tenant/README.md +++ b/examples/multi-tenant/README.md @@ -1,7 +1,7 @@ Keycloak Example - Multi Tenancy ======================================= -The following example was tested on Wildfly 8.1.0.Final and should be compatible with any JBoss AS, JBoss EAP or Wildfly that supports Java EE 7. +The following example was tested on Wildfly 8.1.0.Final and JBoss EAP 6.3. It should be compatible with any JBoss AS, JBoss EAP or Wildfly that supports Java EE 7. This example demonstrates the simplest possible scenario for Keycloak Multi Tenancy support. Multi Tenancy is understood on this context as a single application (WAR) that is deployed on a single or clustered application server, authenticating users from *different realms* against a single or clustered Keycloak server. diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaCookieTokenStore.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaCookieTokenStore.java index ddf06aee3aa..f55bc8bceaa 100644 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaCookieTokenStore.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaCookieTokenStore.java @@ -49,6 +49,12 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore { if (authenticatedPrincipal != null) { log.debug("remote logged in already. Establish state from cookie"); RefreshableKeycloakSecurityContext securityContext = authenticatedPrincipal.getKeycloakSecurityContext(); + + if (!securityContext.getRealm().equals(deployment.getRealm())) { + log.debug("Account from cookie is from a different realm than for the request."); + return false; + } + securityContext.setCurrentRequestInfo(deployment, this); Set roles = AdapterUtils.getRolesFromSecurityContext(securityContext); GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles, securityContext); @@ -97,11 +103,6 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore { RefreshableKeycloakSecurityContext session = principal.getKeycloakSecurityContext(); - if (!session.getRealm().equals(deployment.getRealm())) { - log.debug("Account from cookie is from a different realm than for the request."); - return null; - } - if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return principal; boolean success = session.refreshExpiredToken(false); if (success && session.isActive()) return principal; diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSessionTokenStore.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSessionTokenStore.java index b5361ce94b1..0d5dc3f79d3 100644 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSessionTokenStore.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSessionTokenStore.java @@ -38,11 +38,6 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore { RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); if (session == null) return; - if (!deployment.getRealm().equals(session.getRealm())) { - log.debug("Account from cookie is from a different realm than for the request."); - return; - } - // just in case session got serialized if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this); @@ -69,16 +64,23 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore { if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) return false; log.debug("remote logged in already. Establish state from session"); - GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal(); - request.setUserPrincipal(principal); - request.setAuthType("KEYCLOAK"); RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); if (securityContext != null) { + + if (!deployment.getRealm().equals(securityContext.getRealm())) { + log.debug("Account from cookie is from a different realm than for the request."); + return false; + } + securityContext.setCurrentRequestInfo(deployment, this); request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); } + GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal(); + request.setUserPrincipal(principal); + request.setAuthType("KEYCLOAK"); + ((CatalinaRequestAuthenticator)authenticator).restoreRequest(); return true; } diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java index 843b039488a..1c0bf46c30e 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java @@ -66,12 +66,12 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif public void logout(Request request) throws ServletException { KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); if (ksc != null) { - request.removeAttribute(KeycloakSecurityContext.class.getName()); CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment); tokenStore.logout(); + request.removeAttribute(KeycloakSecurityContext.class.getName()); } super.logout(request); } @@ -126,7 +126,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent) // Outcome: adapter is left unconfigured - String configResolverClass = (String) context.getServletContext().getAttribute("keycloak.config.resolver"); + String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver"); if (configResolverClass != null) { try { KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance(); diff --git a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaCookieTokenStore.java b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaCookieTokenStore.java index 1678dd98952..4169e5a9e67 100644 --- a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaCookieTokenStore.java +++ b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaCookieTokenStore.java @@ -47,6 +47,12 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore { if (authenticatedPrincipal != null) { log.fine("remote logged in already. Establish state from cookie"); RefreshableKeycloakSecurityContext securityContext = authenticatedPrincipal.getKeycloakSecurityContext(); + + if (!securityContext.getRealm().equals(deployment.getRealm())) { + log.fine("Account from cookie is from a different realm than for the request."); + return false; + } + securityContext.setCurrentRequestInfo(deployment, this); Set roles = AdapterUtils.getRolesFromSecurityContext(securityContext); GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles, securityContext); @@ -95,11 +101,6 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore { RefreshableKeycloakSecurityContext session = principal.getKeycloakSecurityContext(); - if (!session.getRealm().equals(deployment.getRealm())) { - log.fine("Account from cookie is from a different realm than for the request."); - return null; - } - if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return principal; boolean success = session.refreshExpiredToken(false); if (success && session.isActive()) return principal; diff --git a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaSessionTokenStore.java b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaSessionTokenStore.java index 6cc3ce699f6..c47f2b2bbb4 100644 --- a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaSessionTokenStore.java +++ b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaSessionTokenStore.java @@ -36,11 +36,6 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore { RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); if (session == null) return; - if (!deployment.getRealm().equals(session.getRealm())) { - log.fine("Account from cookie is from a different realm than for the request."); - return; - } - // just in case session got serialized if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this); @@ -67,16 +62,23 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore { if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) return false; log.fine("remote logged in already. Establish state from session"); - GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal(); - request.setUserPrincipal(principal); - request.setAuthType("KEYCLOAK"); RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); if (securityContext != null) { + + if (!deployment.getRealm().equals(securityContext.getRealm())) { + log.fine("Account from cookie is from a different realm than for the request."); + return false; + } + securityContext.setCurrentRequestInfo(deployment, this); request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); } + GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal(); + request.setUserPrincipal(principal); + request.setAuthType("KEYCLOAK"); + ((CatalinaRequestAuthenticator)authenticator).restoreRequest(); return true; } diff --git a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java index 984f4d93b05..f471242b7bf 100755 --- a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java +++ b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java @@ -73,12 +73,12 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif public void logout(Request request) throws ServletException { KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); if (ksc != null) { - request.removeAttribute(KeycloakSecurityContext.class.getName()); CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment); tokenStore.logout(); + request.removeAttribute(KeycloakSecurityContext.class.getName()); } super.logout(request); } @@ -103,7 +103,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent) // Outcome: adapter is left unconfigured - String configResolverClass = (String) context.getServletContext().getAttribute("keycloak.config.resolver"); + String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver"); if (configResolverClass != null) { try { KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();