diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml index 14ed2cd3d6..3c03ca80ab 100755 --- a/distribution/modules/build.xml +++ b/distribution/modules/build.xml @@ -73,6 +73,7 @@ + diff --git a/integration/as7-eap6/adapter/pom.xml b/integration/as7-eap6/adapter/pom.xml index 513c13928b..d9eaa15905 100755 --- a/integration/as7-eap6/adapter/pom.xml +++ b/integration/as7-eap6/adapter/pom.xml @@ -77,6 +77,25 @@ 7.1.2.Final provided + + org.keycloak + keycloak-tomcat-core-adapter + ${project.version} + + + org.apache.tomcat + tomcat-servlet-api + + + org.apache.tomcat + tomcat-catalina + + + org.apache.tomcat + catalina + + + junit junit 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 deleted file mode 100755 index d23da0171d..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.keycloak.adapters.as7; - -import org.apache.catalina.Container; -import org.apache.catalina.Valve; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; -import org.jboss.logging.Logger; -import org.keycloak.adapters.AdapterDeploymentContext; -import org.keycloak.adapters.AuthenticatedActionsHandler; -import org.keycloak.adapters.KeycloakDeployment; - -import javax.management.ObjectName; -import javax.servlet.ServletException; -import java.io.IOException; - -/** - * Pre-installed actions that must be authenticated - *

- * Actions include: - *

- * CORS Origin Check and Response headers - * k_query_bearer_token: Get bearer token from server for Javascripts CORS requests - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class AuthenticatedActionsValve extends ValveBase { - private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class); - protected AdapterDeploymentContext deploymentContext; - - public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container, ObjectName controller) { - this.deploymentContext = deploymentContext; - if (next == null) throw new RuntimeException("Next valve is null!!!"); - setNext(next); - setContainer(container); - setController(controller); - } - - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI()); - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); - KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); - if (deployment != null && deployment.isConfigured()) { - AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response)); - if (handler.handledRequest()) { - return; - } - - } - getNext().invoke(request, response); - } -} 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 deleted file mode 100755 index 359e84b255..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaCookieTokenStore.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.keycloak.adapters.as7; - -import java.util.Set; - -import org.apache.catalina.connector.Request; -import org.apache.catalina.realm.GenericPrincipal; -import org.jboss.logging.Logger; -import org.keycloak.KeycloakPrincipal; -import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.AdapterTokenStore; -import org.keycloak.adapters.AdapterUtils; -import org.keycloak.adapters.CookieTokenStore; -import org.keycloak.adapters.HttpFacade; -import org.keycloak.adapters.KeycloakAccount; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.adapters.RequestAuthenticator; - -/** - * Handle storage of token info in cookie. Per-request object. - * - * @author Marek Posolda - */ -public class CatalinaCookieTokenStore implements AdapterTokenStore { - - private static final Logger log = Logger.getLogger(CatalinaCookieTokenStore.class); - - private Request request; - private HttpFacade facade; - private KeycloakDeployment deployment; - - private KeycloakPrincipal authenticatedPrincipal; - - public CatalinaCookieTokenStore(Request request, HttpFacade facade, KeycloakDeployment deployment) { - this.request = request; - this.facade = facade; - this.deployment = deployment; - } - - - @Override - public void checkCurrentToken() { - this.authenticatedPrincipal = checkPrincipalFromCookie(); - } - - @Override - public boolean isCached(RequestAuthenticator authenticator) { - // Assuming authenticatedPrincipal set by previous call of checkCurrentToken() during this request - 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); - - request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); - request.setUserPrincipal(principal); - request.setAuthType("KEYCLOAK"); - return true; - } else { - return false; - } - } - - @Override - public void saveAccountInfo(KeycloakAccount account) { - RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext(); - CookieTokenStore.setTokenCookie(deployment, facade, securityContext); - } - - @Override - public void logout() { - CookieTokenStore.removeCookie(facade); - - } - - @Override - public void refreshCallback(RefreshableKeycloakSecurityContext secContext) { - CookieTokenStore.setTokenCookie(deployment, facade, secContext); - } - - /** - * Verify if we already have authenticated and active principal in cookie. Perform refresh if it's not active - * - * @return valid principal - */ - protected KeycloakPrincipal checkPrincipalFromCookie() { - KeycloakPrincipal principal = CookieTokenStore.getPrincipalFromCookie(deployment, facade, this); - if (principal == null) { - log.debug("Account was not in cookie or was invalid"); - return null; - } - - RefreshableKeycloakSecurityContext session = principal.getKeycloakSecurityContext(); - - if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return principal; - boolean success = session.refreshExpiredToken(false); - if (success && session.isActive()) return principal; - - log.debugf("Cleanup and expire cookie for user %s after failed refresh", principal.getName()); - request.setUserPrincipal(null); - request.setAuthType(null); - CookieTokenStore.removeCookie(facade); - return null; - } -} diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java deleted file mode 100755 index ce7d27cb84..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.keycloak.adapters.as7; - -import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.HttpFacade; - -import javax.security.cert.X509Certificate; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CatalinaHttpFacade implements HttpFacade { - protected org.apache.catalina.connector.Request request; - protected HttpServletResponse response; - protected RequestFacade requestFacade = new RequestFacade(); - protected ResponseFacade responseFacade = new ResponseFacade(); - - protected class RequestFacade implements Request { - @Override - public String getURI() { - StringBuffer buf = request.getRequestURL(); - if (request.getQueryString() != null) { - buf.append('?').append(request.getQueryString()); - } - return buf.toString(); - } - - @Override - public boolean isSecure() { - return request.isSecure(); - } - - @Override - public String getQueryParamValue(String paramName) { - return request.getParameter(paramName); - } - - @Override - public Cookie getCookie(String cookieName) { - if (request.getCookies() == null) return null; - javax.servlet.http.Cookie cookie = null; - for (javax.servlet.http.Cookie c : request.getCookies()) { - if (c.getName().equals(cookieName)) { - cookie = c; - break; - } - } - if (cookie == null) return null; - return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath()); - } - - @Override - public List getHeaders(String name) { - Enumeration headers = request.getHeaders(name); - if (headers == null) return null; - List list = new ArrayList(); - while (headers.hasMoreElements()) { - list.add(headers.nextElement()); - } - return list; - } - - @Override - public InputStream getInputStream() { - try { - return request.getInputStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public String getMethod() { - return request.getMethod(); - } - - @Override - public String getHeader(String name) { - return request.getHeader(name); - } - - @Override - public String getRemoteAddr() { - return request.getRemoteAddr(); - } - } - - protected class ResponseFacade implements Response { - protected boolean ended; - - @Override - public void setStatus(int status) { - response.setStatus(status); - } - - @Override - public void addHeader(String name, String value) { - response.addHeader(name, value); - } - - @Override - public void setHeader(String name, String value) { - response.setHeader(name, value); - } - - @Override - public void resetCookie(String name, String path) { - setCookie(name, "", null, path, 0, false, false); - } - - @Override - public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) { - javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(name, value); - if (domain != null) cookie.setDomain(domain); - if (path != null) cookie.setPath(path); - if (secure) cookie.setSecure(true); - if (httpOnly) cookie.setHttpOnly(httpOnly); - cookie.setMaxAge(maxAge); - response.addCookie(cookie); - } - - @Override - public OutputStream getOutputStream() { - try { - return response.getOutputStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void sendError(int code, String message) { - try { - response.sendError(code, message); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void end() { - ended = true; - } - - public boolean isEnded() { - return ended; - } - } - - public CatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) { - this.request = request; - this.response = response; - } - - @Override - public Request getRequest() { - return requestFacade; - } - - @Override - public Response getResponse() { - return responseFacade; - } - - @Override - public KeycloakSecurityContext getSecurityContext() { - return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); - } - - @Override - public X509Certificate[] getCertificateChain() { - throw new IllegalStateException("Not supported yet"); - } - - public boolean isEnded() { - return responseFacade.isEnded(); - } -} diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java deleted file mode 100755 index 7544e66725..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaRequestAuthenticator.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.keycloak.adapters.as7; - -import org.apache.catalina.authenticator.Constants; -import org.apache.catalina.connector.Request; -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.KeycloakAccount; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.OAuthRequestAuthenticator; -import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.adapters.RequestAuthenticator; -import org.keycloak.enums.TokenStore; - -import java.io.IOException; -import java.security.Principal; -import java.util.Set; - -import javax.servlet.http.HttpSession; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CatalinaRequestAuthenticator extends RequestAuthenticator { - - private static final Logger log = Logger.getLogger(CatalinaRequestAuthenticator.class); - protected KeycloakAuthenticatorValve valve; - protected Request request; - - public CatalinaRequestAuthenticator(KeycloakDeployment deployment, - KeycloakAuthenticatorValve valve, AdapterTokenStore tokenStore, - CatalinaHttpFacade facade, - Request request) { - super(facade, deployment, tokenStore, request.getConnector().getRedirectPort()); - this.valve = valve; - this.request = request; - } - - @Override - protected OAuthRequestAuthenticator createOAuthAuthenticator() { - return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort) { - @Override - protected void saveRequest() { - try { - // Support saving request just for TokenStore.SESSION TODO: Add to tokenStore spi? - if (deployment.getTokenStore() == TokenStore.SESSION) { - valve.keycloakSaveRequest(request); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - @Override - protected void completeOAuthAuthentication(final KeycloakPrincipal skp) { - final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext(); - final Set roles = AdapterUtils.getRolesFromSecurityContext(securityContext); - KeycloakAccount account = new KeycloakAccount() { - - @Override - public Principal getPrincipal() { - return skp; - } - - @Override - public Set getRoles() { - return roles; - } - - @Override - public KeycloakSecurityContext getKeycloakSecurityContext() { - return securityContext; - } - - }; - - request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); - this.tokenStore.saveAccountInfo(account); - } - - @Override - protected void completeBearerAuthentication(KeycloakPrincipal principal, String method) { - RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext(); - Set roles = AdapterUtils.getRolesFromSecurityContext(securityContext); - if (log.isDebugEnabled()) { - log.debug("Completing bearer authentication. Bearer roles: " + roles); - } - Principal generalPrincipal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), principal, roles, securityContext); - request.setUserPrincipal(generalPrincipal); - request.setAuthType(method); - request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); - } - - protected void restoreRequest() { - if (request.getSessionInternal().getNote(Constants.FORM_REQUEST_NOTE) != null) { - if (valve.keycloakRestoreRequest(request)) { - log.debug("restoreRequest"); - } else { - log.debug("Restore of original request failed"); - throw new RuntimeException("Restore of original request failed"); - } - } - } - - @Override - protected String getHttpSessionId(boolean create) { - HttpSession session = request.getSession(create); - return session != null ? session.getId() : null; - } -} 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 deleted file mode 100755 index 41266cfc01..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSessionTokenStore.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.keycloak.adapters.as7; - -import java.util.Set; - -import org.apache.catalina.Session; -import org.apache.catalina.connector.Request; -import org.apache.catalina.realm.GenericPrincipal; -import org.jboss.logging.Logger; -import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.AdapterTokenStore; -import org.keycloak.adapters.KeycloakAccount; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.adapters.RequestAuthenticator; - -/** - * Handle storage of token info in HTTP Session. Per-request object - * - * @author Marek Posolda - */ -public class CatalinaSessionTokenStore implements AdapterTokenStore { - - private static final Logger log = Logger.getLogger(CatalinaSessionTokenStore.class); - - private Request request; - private KeycloakDeployment deployment; - private CatalinaUserSessionManagement sessionManagement; - - public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment, CatalinaUserSessionManagement sessionManagement) { - this.request = request; - this.deployment = deployment; - this.sessionManagement = sessionManagement; - } - - @Override - public void checkCurrentToken() { - if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) return; - RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); - if (session == null) return; - - // just in case session got serialized - if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this); - - if (session.isActive() && !session.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 = session.refreshExpiredToken(false); - if (success && session.isActive()) return; - - // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session - Session catalinaSession = request.getSessionInternal(); - log.debugf("Cleanup and expire session %s after failed refresh", catalinaSession.getId()); - catalinaSession.removeNote(KeycloakSecurityContext.class.getName()); - request.setUserPrincipal(null); - request.setAuthType(null); - catalinaSession.setPrincipal(null); - catalinaSession.setAuthType(null); - catalinaSession.expire(); - } - - @Override - public boolean isCached(RequestAuthenticator authenticator) { - if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) - return false; - log.debug("remote logged in already. Establish state from session"); - - 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; - } - - @Override - public void saveAccountInfo(KeycloakAccount account) { - RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext(); - Set roles = account.getRoles(); - GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext); - - Session session = request.getSessionInternal(true); - session.setPrincipal(principal); - session.setAuthType("OAUTH"); - session.setNote(KeycloakSecurityContext.class.getName(), securityContext); - String username = securityContext.getToken().getSubject(); - log.debug("userSessionManagement.login: " + username); - this.sessionManagement.login(session); - } - - @Override - public void logout() { - Session session = request.getSessionInternal(false); - if (session != null) { - session.removeNote(KeycloakSecurityContext.class.getName()); - } - } - - @Override - public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) { - // no-op - } -} diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagement.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagement.java deleted file mode 100755 index ffb806e1ac..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagement.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.keycloak.adapters.as7; - -import org.apache.catalina.Manager; -import org.apache.catalina.Session; -import org.apache.catalina.SessionEvent; -import org.apache.catalina.SessionListener; -import org.apache.catalina.realm.GenericPrincipal; -import org.jboss.logging.Logger; - -import java.io.IOException; -import java.util.List; - -/** - * Manages relationship to users and sessions so that forced admin logout can be implemented - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CatalinaUserSessionManagement implements SessionListener { - private static final Logger log = Logger.getLogger(CatalinaUserSessionManagement.class); - - public void login(Session session) { - session.addSessionListener(this); - } - - public void logoutAll(Manager sessionManager) { - Session[] allSessions = sessionManager.findSessions(); - for (Session session : allSessions) { - logoutSession(session); - } - } - - public void logoutHttpSessions(Manager sessionManager, List sessionIds) { - log.debug("logoutHttpSessions: " + sessionIds); - - for (String sessionId : sessionIds) { - logoutSession(sessionManager, sessionId); - } - } - - protected void logoutSession(Manager manager, String httpSessionId) { - log.debug("logoutHttpSession: " + httpSessionId); - - Session session; - try { - session = manager.findSession(httpSessionId); - } catch (IOException ioe) { - log.warn("IO exception when looking for session " + httpSessionId, ioe); - return; - } - - logoutSession(session); - } - - protected void logoutSession(Session session) { - try { - session.expire(); - } catch (Exception e) { - log.warnf("Session not present or already invalidated."); - } - } - - public void sessionEvent(SessionEvent event) { - // We only care about session destroyed events - if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType()) - && (!Session.SESSION_PASSIVATED_EVENT.equals(event.getType()))) - return; - - // Look up the single session id associated with this session (if any) - Session session = event.getSession(); - log.debugf("Session %s destroyed", session.getId()); - - GenericPrincipal principal = (GenericPrincipal) session.getPrincipal(); - if (principal == null) return; - session.setPrincipal(null); - session.setAuthType(null); - } -} diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagementWrapper.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagementWrapper.java deleted file mode 100644 index ff7ee07d5e..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaUserSessionManagementWrapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.keycloak.adapters.as7; - -import java.util.List; - -import org.apache.catalina.Manager; -import org.keycloak.adapters.UserSessionManagement; - -/** - * @author Marek Posolda - */ -public class CatalinaUserSessionManagementWrapper implements UserSessionManagement { - - private final CatalinaUserSessionManagement delegate; - private final Manager sessionManager; - - public CatalinaUserSessionManagementWrapper(CatalinaUserSessionManagement delegate, Manager sessionManager) { - this.delegate = delegate; - this.sessionManager = sessionManager; - } - - @Override - public void logoutAll() { - delegate.logoutAll(sessionManager); - } - - @Override - public void logoutHttpSessions(List ids) { - delegate.logoutHttpSessions(sessionManager, ids); - } -} 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 deleted file mode 100755 index c2d42c1762..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java +++ /dev/null @@ -1,255 +0,0 @@ -package org.keycloak.adapters.as7; - -import org.apache.catalina.Context; -import org.apache.catalina.Lifecycle; -import org.apache.catalina.LifecycleEvent; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.LifecycleListener; -import org.apache.catalina.Manager; -import org.apache.catalina.authenticator.FormAuthenticator; -import org.apache.catalina.connector.Request; -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.KeycloakSecurityContext; -import org.keycloak.constants.AdapterConstants; -import org.keycloak.adapters.AdapterDeploymentContext; -import org.keycloak.adapters.AdapterTokenStore; -import org.keycloak.adapters.AuthChallenge; -import org.keycloak.adapters.AuthOutcome; -import org.keycloak.adapters.HttpFacade; -import org.keycloak.adapters.KeycloakDeployment; -import org.keycloak.adapters.KeycloakDeploymentBuilder; -import org.keycloak.adapters.NodesRegistrationManagement; -import org.keycloak.adapters.PreAuthActionsHandler; -import org.keycloak.adapters.RefreshableKeycloakSecurityContext; -import org.keycloak.enums.TokenStore; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import org.keycloak.adapters.KeycloakConfigResolver; - -/** - * Web deployment whose security is managed by a remote OAuth Skeleton Key authentication server - *

- * Redirects browser to remote authentication server if not logged in. Also allows OAuth Bearer Token requests - * that contain a Skeleton Key bearer tokens. - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class KeycloakAuthenticatorValve extends FormAuthenticator implements LifecycleListener { - - public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE"; - - private static final Logger log = Logger.getLogger(KeycloakAuthenticatorValve.class); - protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement(); - protected AdapterDeploymentContext deploymentContext; - protected NodesRegistrationManagement nodesRegistrationManagement; - - - @Override - public void start() throws LifecycleException { - super.start(); - StandardContext standardContext = (StandardContext) context; - standardContext.addLifecycleListener(this); - cache = false; - } - - @Override - public void logout(Request request) throws ServletException { - KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); - if (ksc != null) { - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null); - KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); - if (ksc instanceof RefreshableKeycloakSecurityContext) { - ((RefreshableKeycloakSecurityContext) ksc).logout(deployment); - } - - AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment); - tokenStore.logout(); - request.removeAttribute(KeycloakSecurityContext.class.getName()); - } - super.logout(request); - } - - @Override - public void lifecycleEvent(LifecycleEvent event) { - if (event.getType() == Lifecycle.AFTER_START_EVENT) { - init(); - } else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) { - beforeStop(); - } - } - - private static InputStream getJSONFromServletContext(ServletContext servletContext) { - String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME); - if (json == null) { - return null; - } - log.debug("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME); - log.debug(json); - return new ByteArrayInputStream(json.getBytes()); - } - - private static InputStream getConfigInputStream(Context context) { - InputStream is = getJSONFromServletContext(context.getServletContext()); - if (is == null) { - String path = context.getServletContext().getInitParameter("keycloak.config.file"); - if (path == null) { - log.debug("**** using /WEB-INF/keycloak.json"); - is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json"); - } else { - try { - is = new FileInputStream(path); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } - } - return is; - } - - - @SuppressWarnings("UseSpecificCatch") - protected void init() { - // Possible scenarios: - // 1) The deployment has a keycloak.config.resolver specified and it exists: - // Outcome: adapter uses the resolver - // 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) : - // Outcome: adapter is left unconfigured - // 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent) - // Outcome: adapter uses it - // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent) - // Outcome: adapter is left unconfigured - - String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver"); - if (configResolverClass != null) { - try { - KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().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 configInputStream = getConfigInputStream(context); - KeycloakDeployment kd; - if (configInputStream == null) { - log.warn("No adapter configuration. Keycloak is unconfigured and will deny all requests."); - kd = new KeycloakDeployment(); - } else { - kd = KeycloakDeploymentBuilder.build(configInputStream); - } - deploymentContext = new AdapterDeploymentContext(kd); - log.debug("Keycloak is using a per-deployment configuration."); - } - - context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext); - AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer(), getController()); - setNext(actions); - - nodesRegistrationManagement = new NodesRegistrationManagement(); - } - - protected void beforeStop() { - nodesRegistrationManagement.stop(); - } - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - if (log.isTraceEnabled()) { - log.trace("invoke"); - } - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); - Manager sessionManager = request.getContext().getManager(); - CatalinaUserSessionManagementWrapper sessionManagementWrapper = new CatalinaUserSessionManagementWrapper(userSessionManagement, sessionManager); - PreAuthActionsHandler handler = new PreAuthActionsHandler(sessionManagementWrapper, deploymentContext, facade); - if (handler.handleRequest()) { - return; - } - checkKeycloakSession(request, facade); - super.invoke(request, response); - } finally { - } - } - - @Override - public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException { - if (log.isTraceEnabled()) { - log.trace("*** authenticate"); - } - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); - KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); - if (deployment == null || !deployment.isConfigured()) { - log.debug("*** deployment isn't configured return false"); - return false; - } - AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment); - - nodesRegistrationManagement.tryRegister(deployment); - - CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, tokenStore, facade, request); - AuthOutcome outcome = authenticator.authenticate(); - if (outcome == AuthOutcome.AUTHENTICATED) { - if (facade.isEnded()) { - return false; - } - return true; - } - AuthChallenge challenge = authenticator.getChallenge(); - if (challenge != null) { - challenge.challenge(facade); - } - return false; - } - - /** - * Checks that access token is still valid. Will attempt refresh of token if it is not. - * - * @param request - */ - protected void checkKeycloakSession(Request request, HttpFacade facade) { - KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); - AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment); - tokenStore.checkCurrentToken(); - } - - public void keycloakSaveRequest(Request request) throws IOException { - saveRequest(request, request.getSessionInternal(true)); - } - - public boolean keycloakRestoreRequest(Request request) { - try { - return restoreRequest(request, request.getSessionInternal()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) { - AdapterTokenStore store = (AdapterTokenStore)request.getNote(TOKEN_STORE_NOTE); - if (store != null) { - return store; - } - - if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) { - store = new CatalinaSessionTokenStore(request, resolvedDeployment, userSessionManagement); - } else { - store = new CatalinaCookieTokenStore(request, facade, resolvedDeployment); - } - - request.setNote(TOKEN_STORE_NOTE, store); - return store; - } - -} diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/JBossWebPrincipalFactory.java similarity index 92% rename from integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java rename to integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/JBossWebPrincipalFactory.java index f33c4631a2..3d8930ed79 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/JBossWebPrincipalFactory.java @@ -1,4 +1,4 @@ -package org.keycloak.adapters.as7; +package org.keycloak.adapters.jbossweb; import org.apache.catalina.Realm; import org.apache.catalina.realm.GenericPrincipal; @@ -11,6 +11,7 @@ import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.KeycloakAccount; +import org.keycloak.adapters.tomcat.GenericPrincipalFactory; import javax.security.auth.Subject; import java.security.Principal; @@ -26,7 +27,14 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class CatalinaSecurityContextHelper { +public class JBossWebPrincipalFactory extends GenericPrincipalFactory { + + @Override + protected GenericPrincipal createPrincipal(Principal userPrincipal, List roles) { + return null; + } + + @Override public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set roleSet, final KeycloakSecurityContext securityContext) { KeycloakAccount account = new KeycloakAccount() { @Override diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java new file mode 100755 index 0000000000..71e0f19b30 --- /dev/null +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java @@ -0,0 +1,44 @@ +package org.keycloak.adapters.jbossweb; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.deploy.LoginConfig; +import org.apache.catalina.realm.GenericPrincipal; +import org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve; +import org.keycloak.adapters.tomcat.GenericPrincipalFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.security.Principal; +import java.util.List; + +/** + * Keycloak authentication valve + * + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve { + public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws java.io.IOException { + return authenticateInternal(request, response); + } + + @Override + public void start() throws LifecycleException { + StandardContext standardContext = (StandardContext) context; + standardContext.addLifecycleListener(this); + super.start(); + } + + + public void logout(Request request) { + logoutInternal(request); + } + + @Override + protected GenericPrincipalFactory createPrincipalFactory() { + return new JBossWebPrincipalFactory(); + } +} diff --git a/integration/keycloak-as7-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java b/integration/keycloak-as7-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java index 170aff9fa2..d9e4e7d406 100755 --- a/integration/keycloak-as7-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java +++ b/integration/keycloak-as7-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java @@ -28,7 +28,7 @@ import org.jboss.metadata.javaee.spec.ParamValueMetaData; import org.jboss.metadata.web.jboss.JBossWebMetaData; import org.jboss.metadata.web.jboss.ValveMetaData; import org.jboss.metadata.web.spec.LoginConfigMetaData; -import org.keycloak.adapters.as7.KeycloakAuthenticatorValve; +import org.keycloak.adapters.jbossweb.KeycloakAuthenticatorValve; import org.keycloak.subsystem.logging.KeycloakLogger; import java.util.ArrayList; diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java old mode 100644 new mode 100755 index d5c05f086e..39c6ec10cb --- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java +++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorAS7.java @@ -27,7 +27,7 @@ import org.jboss.metadata.javaee.spec.ParamValueMetaData; import org.jboss.metadata.web.jboss.JBossWebMetaData; import org.jboss.metadata.web.jboss.ValveMetaData; import org.jboss.metadata.web.spec.LoginConfigMetaData; -import org.keycloak.adapters.as7.KeycloakAuthenticatorValve; +import org.keycloak.adapters.jbossweb.KeycloakAuthenticatorValve; import org.keycloak.subsystem.logging.KeycloakLogger; import java.util.ArrayList; diff --git a/integration/pom.xml b/integration/pom.xml index 089028f560..7311775f2c 100755 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -18,8 +18,8 @@ jaxrs-oauth-client servlet-oauth-client jboss-adapter-core - as7-eap6/adapter tomcat + as7-eap6/adapter jetty undertow wildfly-adapter diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml index 2f94ba4bca..f271d397e2 100755 --- a/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml +++ b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml @@ -1,5 +1,5 @@ - org.keycloak.adapters.as7.KeycloakAuthenticatorValve + org.keycloak.adapters.jbossweb.KeycloakAuthenticatorValve \ No newline at end of file