From 3fbffc9d7db4021cdad698adf5ccf3e2dfe53022 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Mon, 10 Nov 2014 16:59:31 -0500 Subject: [PATCH] jetty 8 --- distribution/appliance-dist/assembly.xml | 1 + distribution/jetty81-adapter-zip/assembly.xml | 25 + distribution/jetty81-adapter-zip/pom.xml | 53 ++ distribution/war-dist/assembly.xml | 1 + .../jaxrs/JaxrsBearerTokenFilter.java | 1 + .../jetty/{jetty9-core => jetty-core}/pom.xml | 6 +- .../AbstractJettyRequestAuthenticator.java | 21 +- .../AbstractKeycloakJettyAuthenticator.java | 21 +- .../adapters/jetty/JettyCookieTokenStore.java | 0 .../adapters/jetty/JettyHttpFacade.java | 0 .../jetty/JettySessionTokenStore.java | 0 .../jetty/JettyUserSessionManagement.java | 0 integration/jetty/jetty8.1/pom.xml | 105 ++++ .../jetty/JettyRequestAuthenticator.java | 32 ++ .../jetty/KeycloakJettyAuthenticator.java | 44 ++ integration/jetty/jetty9.1/pom.xml | 2 +- .../jetty/KeycloakJettyAuthenticator.java | 20 + integration/jetty/jetty9.2/pom.xml | 2 +- .../jetty/KeycloakJettyAuthenticator.java | 21 + integration/jetty/pom.xml | 3 +- testsuite/jetty/jetty81/pom.xml | 515 ++++++++++++++++++ .../org/keycloak/testsuite/Jetty9Test.java | 229 ++++++++ .../test/resources/jetty-test/demorealm.json | 58 ++ .../jetty-test/webapp/WEB-INF/keycloak.json | 10 + testsuite/pom.xml | 1 + 25 files changed, 1141 insertions(+), 30 deletions(-) create mode 100755 distribution/jetty81-adapter-zip/assembly.xml create mode 100755 distribution/jetty81-adapter-zip/pom.xml rename integration/jetty/{jetty9-core => jetty-core}/pom.xml (91%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java (84%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java (93%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java (100%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java (100%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java (100%) rename integration/jetty/{jetty9-core => jetty-core}/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java (100%) create mode 100755 integration/jetty/jetty8.1/pom.xml create mode 100755 integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java create mode 100755 integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java create mode 100755 testsuite/jetty/jetty81/pom.xml create mode 100755 testsuite/jetty/jetty81/src/test/java/org/keycloak/testsuite/Jetty9Test.java create mode 100755 testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json create mode 100755 testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json diff --git a/distribution/appliance-dist/assembly.xml b/distribution/appliance-dist/assembly.xml index b3307b022c..2ec0bfa03b 100755 --- a/distribution/appliance-dist/assembly.xml +++ b/distribution/appliance-dist/assembly.xml @@ -81,6 +81,7 @@ org.keycloak:keycloak-as7-adapter-dist:zip org.keycloak:keycloak-eap6-adapter-dist:zip org.keycloak:keycloak-tomcat7-adapter-dist:zip + org.keycloak:keycloak-jetty81-adapter-dist:zip org.keycloak:keycloak-jetty91-adapter-dist:zip org.keycloak:keycloak-jetty92-adapter-dist:zip diff --git a/distribution/jetty81-adapter-zip/assembly.xml b/distribution/jetty81-adapter-zip/assembly.xml new file mode 100755 index 0000000000..441f907930 --- /dev/null +++ b/distribution/jetty81-adapter-zip/assembly.xml @@ -0,0 +1,25 @@ + + war-dist + + + zip + + false + + + + false + true + true + + org.keycloak:keycloak-jetty91-adapter + + + org.eclipse.jetty:jetty-server + org.eclipse.jetty:jetty-util + org.eclipse.jetty:jetty-security + + lib/keycloak + + + diff --git a/distribution/jetty81-adapter-zip/pom.xml b/distribution/jetty81-adapter-zip/pom.xml new file mode 100755 index 0000000000..77f11127cc --- /dev/null +++ b/distribution/jetty81-adapter-zip/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + keycloak-parent + org.keycloak + 1.1.0.Beta2-SNAPSHOT + ../../pom.xml + + + keycloak-jetty81-adapter-dist + pom + Keycloak Jetty 8.1.x Adapter Distro + + + + + org.keycloak + keycloak-jetty81-adapter + ${project.version} + + + + + + maven-assembly-plugin + 2.4 + + + assemble + package + + single + + + + assembly.xml + + + target + + + target/assembly/work + + false + + + + + + + + diff --git a/distribution/war-dist/assembly.xml b/distribution/war-dist/assembly.xml index e4550d721e..7a35c6641c 100755 --- a/distribution/war-dist/assembly.xml +++ b/distribution/war-dist/assembly.xml @@ -32,6 +32,7 @@ org.keycloak:keycloak-as7-adapter-dist:zip org.keycloak:keycloak-eap6-adapter-dist:zip org.keycloak:keycloak-tomcat7-adapter-dist:zip + org.keycloak:keycloak-jetty81-adapter-dist:zip org.keycloak:keycloak-jetty91-adapter-dist:zip org.keycloak:keycloak-jetty92-adapter-dist:zip 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 5d700c1a8b..e7ffc5b3ad 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 @@ -90,6 +90,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter { @Override public boolean isUserInRole(String role) { + if (access == null) return false; if (access.getRoles() == null) return false; return access.getRoles().contains(role); } diff --git a/integration/jetty/jetty9-core/pom.xml b/integration/jetty/jetty-core/pom.xml similarity index 91% rename from integration/jetty/jetty9-core/pom.xml rename to integration/jetty/jetty-core/pom.xml index dc28ab39c6..dabec6c9df 100755 --- a/integration/jetty/jetty9-core/pom.xml +++ b/integration/jetty/jetty-core/pom.xml @@ -9,10 +9,10 @@ 4.0.0 - keycloak-jetty9-core - Keycloak Jetty 9.x Core Integration + keycloak-jetty-core + Keycloak Jetty Core Integration - 9.1.5.v20140505 + 8.1.16.v20140903 diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java similarity index 84% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java index 4edb4a34a8..ee6ffaeb09 100755 --- a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettyRequestAuthenticator.java @@ -1,9 +1,7 @@ package org.keycloak.adapters.jetty; -import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.security.authentication.FormAuthenticator; -import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.MultiMap; import org.jboss.logging.Logger; @@ -29,6 +27,7 @@ import java.util.Set; * @version $Revision: 1 $ */ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthenticator { + public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD"; protected static final Logger log = Logger.getLogger(AbstractJettyRequestAuthenticator.class); protected AbstractKeycloakJettyAuthenticator valve; protected Request request; @@ -46,7 +45,7 @@ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthentic @Override protected void saveRequest() { if (deployment.getTokenStore() == TokenStore.SESSION) { - saveServletRequest(request, request.getSession()); + saveServletRequest(); } } }; @@ -107,11 +106,10 @@ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthentic */ MultiMap j_post = (MultiMap) session.getAttribute(FormAuthenticator.__J_POST); if (j_post != null) { - Request base_request = HttpChannel.getCurrentHttpChannel().getRequest(); - restoreFormParameters(j_post, base_request); + restoreFormParameters(j_post, request); } session.removeAttribute(FormAuthenticator.__J_URI); - session.removeAttribute(FormAuthenticator.__J_METHOD); + session.removeAttribute(__J_METHOD); session.removeAttribute(FormAuthenticator.__J_POST); // } } @@ -124,8 +122,9 @@ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthentic return session != null ? session.getId() : null; } - protected void saveServletRequest(HttpServletRequest request, HttpSession session) { + protected void saveServletRequest() { // remember the current URI + HttpSession session = request.getSession(); synchronized (session) { // But only if it is not set already, or we save every uri that leads to a login form redirect if (session.getAttribute(FormAuthenticator.__J_URI) == null) { @@ -133,12 +132,10 @@ public abstract class AbstractJettyRequestAuthenticator extends RequestAuthentic if (request.getQueryString() != null) buf.append("?").append(request.getQueryString()); session.setAttribute(FormAuthenticator.__J_URI, buf.toString()); - session.setAttribute(FormAuthenticator.__J_METHOD, request.getMethod()); + session.setAttribute(__J_METHOD, request.getMethod()); - if (MimeTypes.Type.FORM_ENCODED.is(request.getContentType()) && HttpMethod.POST.is(request.getMethod())) { - Request base_request = (request instanceof Request) ? (Request) request : HttpChannel - .getCurrentHttpChannel().getRequest(); - MultiMap formParameters = extractFormParameters(base_request); + if ("application/x-www-form-urlencoded".equals(request.getContentType()) && "POST".equalsIgnoreCase(request.getMethod())) { + MultiMap formParameters = extractFormParameters(request); session.setAttribute(FormAuthenticator.__J_POST, formParameters); } } diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java similarity index 93% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java index 69f025aea0..e2e2cba8b6 100755 --- a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java @@ -6,7 +6,6 @@ import org.eclipse.jetty.security.UserAuthentication; import org.eclipse.jetty.security.authentication.DeferredAuthentication; import org.eclipse.jetty.security.authentication.LoginAuthenticator; import org.eclipse.jetty.server.Authentication; -import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.handler.ContextHandler; @@ -196,7 +195,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica if (log.isTraceEnabled()) { log.trace("*** authenticate"); } - Request request = HttpChannel.getCurrentHttpChannel().getRequest(); + Request request = resolveRequest(req); JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse)res); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment == null || !deployment.isConfigured()) { @@ -235,6 +234,10 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica return Authentication.SEND_CONTINUE; } + + + protected abstract Request resolveRequest(ServletRequest req); + protected abstract AbstractJettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore); @Override @@ -247,25 +250,19 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica Authentication authentication = request.getAuthentication(); if (!(authentication instanceof KeycloakAuthentication)) { UserIdentity userIdentity = createIdentity(principal); - authentication = new KeycloakAuthentication(getAuthMethod(), userIdentity); + authentication = createAuthentication(userIdentity); request.setAuthentication(authentication); } return authentication; } - public static class KeycloakAuthentication extends UserAuthentication + protected abstract Authentication createAuthentication(UserIdentity userIdentity); + + public static abstract class KeycloakAuthentication extends UserAuthentication { public KeycloakAuthentication(String method, UserIdentity userIdentity) { super(method, userIdentity); } - @Override - public void logout() { - Request request = HttpChannel.getCurrentHttpChannel().getRequest(); - logoutCurrent(request); - } - - - } } diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java similarity index 100% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java similarity index 100% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java similarity index 100% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java diff --git a/integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java similarity index 100% rename from integration/jetty/jetty9-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java diff --git a/integration/jetty/jetty8.1/pom.xml b/integration/jetty/jetty8.1/pom.xml new file mode 100755 index 0000000000..3e9af18574 --- /dev/null +++ b/integration/jetty/jetty8.1/pom.xml @@ -0,0 +1,105 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Beta2-SNAPSHOT + ../../../pom.xml + + 4.0.0 + + keycloak-jetty81-adapter + Keycloak Jetty 8.1.x Integration + + 8.1.16.v20140903 + + + + + + org.jboss.logging + jboss-logging + ${jboss.logging.version} + + + org.keycloak + keycloak-core + ${project.version} + + + org.keycloak + keycloak-adapter-core + ${project.version} + + + org.keycloak + keycloak-jetty-core + ${project.version} + + + org.apache.httpcomponents + httpclient + ${keycloak.apache.httpcomponents.version} + + + net.iharder + base64 + + + org.bouncycastle + bcprov-jdk16 + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-mapper-asl + + + org.codehaus.jackson + jackson-xc + + + org.eclipse.jetty + jetty-server + ${jetty9.version} + compile + + + + org.eclipse.jetty + jetty-util + ${jetty9.version} + compile + + + + org.eclipse.jetty + jetty-security + ${jetty9.version} + compile + + + + junit + junit + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + + + diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java new file mode 100755 index 0000000000..60059f2b6f --- /dev/null +++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java @@ -0,0 +1,32 @@ +package org.keycloak.adapters.jetty; + +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.MultiMap; +import org.keycloak.adapters.AdapterTokenStore; +import org.keycloak.adapters.KeycloakDeployment; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class JettyRequestAuthenticator extends AbstractJettyRequestAuthenticator { + + public JettyRequestAuthenticator(KeycloakDeployment deployment, + AbstractKeycloakJettyAuthenticator valve, AdapterTokenStore tokenStore, + JettyHttpFacade facade, + Request request) { + super(facade, deployment, tokenStore, -1, valve, request); + } + + + @Override + protected MultiMap extractFormParameters(Request base_request) { + MultiMap formParameters = new MultiMap(); + base_request.extractParameters(); + return base_request.getParameters(); + } + @Override + protected void restoreFormParameters(MultiMap j_post, Request base_request) { + base_request.setParameters(j_post); + } +} diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java new file mode 100755 index 0000000000..06e1d99374 --- /dev/null +++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -0,0 +1,44 @@ +package org.keycloak.adapters.jetty; + +import org.eclipse.jetty.server.AbstractHttpConnection; +import org.eclipse.jetty.server.Authentication; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.UserIdentity; +import org.keycloak.adapters.AdapterTokenStore; +import org.keycloak.adapters.KeycloakDeployment; + +import javax.servlet.ServletRequest; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator { + + public KeycloakJettyAuthenticator() { + super(); + } + + + @Override + protected AbstractJettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore) { + return new JettyRequestAuthenticator(deployment, this, tokenStore, facade, request); + } + + @Override + protected Request resolveRequest(ServletRequest req) { + return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest(); + } + + @Override + protected Authentication createAuthentication(UserIdentity userIdentity) { + return new KeycloakAuthentication(getAuthMethod(), userIdentity) { + @Override + public void logout() { + logoutCurrent(AbstractHttpConnection.getCurrentConnection().getRequest()); + } + }; + } + + +} diff --git a/integration/jetty/jetty9.1/pom.xml b/integration/jetty/jetty9.1/pom.xml index 79ac91e2fd..0e0a8d5006 100755 --- a/integration/jetty/jetty9.1/pom.xml +++ b/integration/jetty/jetty9.1/pom.xml @@ -34,7 +34,7 @@ org.keycloak - keycloak-jetty9-core + keycloak-jetty-core ${project.version} diff --git a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java index 7153370203..7ce92f8782 100755 --- a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -1,9 +1,14 @@ package org.keycloak.adapters.jetty; +import org.eclipse.jetty.server.Authentication; +import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.UserIdentity; import org.keycloak.adapters.AdapterTokenStore; import org.keycloak.adapters.KeycloakDeployment; +import javax.servlet.ServletRequest; + /** * @author Bill Burke * @version $Revision: 1 $ @@ -20,5 +25,20 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat return new JettyRequestAuthenticator(deployment, this, tokenStore, facade, request); } + @Override + protected Request resolveRequest(ServletRequest req) { + return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest(); + } + + @Override + protected Authentication createAuthentication(UserIdentity userIdentity) { + return new KeycloakAuthentication(getAuthMethod(), userIdentity) { + @Override + public void logout() { + logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest()); + } + }; + } + } diff --git a/integration/jetty/jetty9.2/pom.xml b/integration/jetty/jetty9.2/pom.xml index 42e549dc66..8fb5cb63f1 100755 --- a/integration/jetty/jetty9.2/pom.xml +++ b/integration/jetty/jetty9.2/pom.xml @@ -34,7 +34,7 @@ org.keycloak - keycloak-jetty9-core + keycloak-jetty-core ${project.version} diff --git a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java index 7153370203..d38e7d44cc 100755 --- a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -1,9 +1,14 @@ package org.keycloak.adapters.jetty; +import org.eclipse.jetty.server.Authentication; +import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.UserIdentity; import org.keycloak.adapters.AdapterTokenStore; import org.keycloak.adapters.KeycloakDeployment; +import javax.servlet.ServletRequest; + /** * @author Bill Burke * @version $Revision: 1 $ @@ -20,5 +25,21 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat return new JettyRequestAuthenticator(deployment, this, tokenStore, facade, request); } + @Override + protected Request resolveRequest(ServletRequest req) { + return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest(); + } + + @Override + protected Authentication createAuthentication(UserIdentity userIdentity) { + return new KeycloakAuthentication(getAuthMethod(), userIdentity) { + @Override + public void logout() { + logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest()); + } + }; + } + + } diff --git a/integration/jetty/pom.xml b/integration/jetty/pom.xml index 64d14b5d83..fbe87901db 100755 --- a/integration/jetty/pom.xml +++ b/integration/jetty/pom.xml @@ -14,7 +14,8 @@ pom - jetty9-core + jetty-core + jetty8.1 jetty9.2 jetty9.1 diff --git a/testsuite/jetty/jetty81/pom.xml b/testsuite/jetty/jetty81/pom.xml new file mode 100755 index 0000000000..add48dad52 --- /dev/null +++ b/testsuite/jetty/jetty81/pom.xml @@ -0,0 +1,515 @@ + + + + keycloak-testsuite-pom + org.keycloak + 1.1.0.Beta2-SNAPSHOT + ../../pom.xml + + 4.0.0 + + keycloak-testsuite-jetty81 + Keycloak Jetty 8.1.x Integration TestSuite + + 8.1.16.v20140903 + + + + + + org.keycloak + keycloak-dependencies-server-all + ${project.version} + pom + + + org.keycloak + keycloak-admin-client + ${project.version} + + + log4j + log4j + + + org.slf4j + slf4j-api + 1.6.1 + + + org.slf4j + slf4j-log4j12 + 1.6.1 + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + + + org.jboss.resteasy + jaxrs-api + ${resteasy.version.latest} + + + org.jboss.resteasy + resteasy-jaxrs + ${resteasy.version.latest} + + + log4j + log4j + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-simple + + + + + org.jboss.resteasy + resteasy-client + ${resteasy.version.latest} + + + org.jboss.resteasy + resteasy-crypto + ${resteasy.version.latest} + + + org.jboss.resteasy + resteasy-multipart-provider + ${resteasy.version.latest} + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version.latest} + + + org.jboss.resteasy + resteasy-undertow + ${resteasy.version.latest} + + + com.google.zxing + javase + + + org.bouncycastle + bcprov-jdk16 + + + org.apache.httpcomponents + httpclient + ${keycloak.apache.httpcomponents.version} + + + org.keycloak + keycloak-ldap-federation + ${project.version} + + + org.keycloak + keycloak-undertow-adapter + ${project.version} + + + org.keycloak + keycloak-jetty81-adapter + ${project.version} + + + org.jboss.logging + jboss-logging + + + io.undertow + undertow-servlet + + + io.undertow + undertow-core + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-mapper-asl + + + org.codehaus.jackson + jackson-xc + + + junit + junit + + + org.hamcrest + hamcrest-all + + + org.hibernate.javax.persistence + hibernate-jpa-2.0-api + + + com.h2database + h2 + + + org.hibernate + hibernate-entitymanager + + + com.icegreen + greenmail + + + org.slf4j + slf4j-api + + + + + org.infinispan + infinispan-core + + + org.seleniumhq.selenium + selenium-java + + + xml-apis + xml-apis + + + org.seleniumhq.selenium + selenium-chrome-driver + + + org.wildfly + wildfly-undertow + ${wildfly.version} + test + + + org.keycloak + keycloak-testsuite-integration + ${project.version} + test + + + org.keycloak + keycloak-testsuite-integration + ${project.version} + test-jar + test + + + org.eclipse.jetty + jetty-util + ${jetty9.version} + provided + + + + org.eclipse.jetty + jetty-webapp + ${jetty9.version} + provided + + + + org.eclipse.jetty + jetty-security + ${jetty9.version} + provided + + + + org.eclipse.jetty + jetty-servlet + ${jetty9.version} + provided + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.codehaus.mojo + exec-maven-plugin + + ${project.basedir} + + + + + + + + keycloak-server + + + + org.codehaus.mojo + exec-maven-plugin + + org.keycloak.testutils.KeycloakServer + + + + + + + mail-server + + + + org.codehaus.mojo + exec-maven-plugin + + org.keycloak.testutils.MailServer + + + + + + + totp + + + + org.codehaus.mojo + exec-maven-plugin + + org.keycloak.testutils.TotpGenerator + + + + + + + + jpa + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + jpa + jpa + jpa + jpa + + + + + + + + + mongo + + + localhost + 27018 + keycloak + true + 127.0.0.1 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + test + integration-test + + test + + + + mongo + mongo + mongo + mongo + ${keycloak.connectionsMongo.host} + ${keycloak.connectionsMongo.port} + ${keycloak.connectionsMongo.db} + ${keycloak.connectionsMongo.clearOnStartup} + ${keycloak.connectionsMongo.bindIp} + + + + + default-test + + true + + + + + + + + com.github.joelittlejohn.embedmongo + embedmongo-maven-plugin + + + start-mongodb + pre-integration-test + + start + + + ${keycloak.connectionsMongo.port} + file + ${project.build.directory}/mongodb.log + ${keycloak.connectionsMongo.bindIp} + + + + stop-mongodb + post-integration-test + + stop + + + + + + + + + + + infinispan + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + infinispan + infinispan + infinispan + + + + + + + + + + + + keycloak.connectionsJpa.driver + com.mysql.jdbc.Driver + + + mysql + + + mysql + mysql-connector-java + ${mysql.version} + + + + + + + + + keycloak.connectionsJpa.driver + org.postgresql.Driver + + + postgresql + + + org.postgresql + postgresql + ${postgresql.version} + + + + + + clean-jpa + + + + org.liquibase + liquibase-maven-plugin + + META-INF/jpa-changelog-master.xml + + ${keycloak.connectionsJpa.url} + ${keycloak.connectionsJpa.driver} + ${keycloak.connectionsJpa.user} + ${keycloak.connectionsJpa.password} + + false + + + + clean-jpa + clean + + dropAll + + + + + + + + + diff --git a/testsuite/jetty/jetty81/src/test/java/org/keycloak/testsuite/Jetty9Test.java b/testsuite/jetty/jetty81/src/test/java/org/keycloak/testsuite/Jetty9Test.java new file mode 100755 index 0000000000..8995fa954f --- /dev/null +++ b/testsuite/jetty/jetty81/src/test/java/org/keycloak/testsuite/Jetty9Test.java @@ -0,0 +1,229 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2012, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.keycloak.testsuite; + +import org.eclipse.jetty.security.ConstraintMapping; +import org.eclipse.jetty.security.ConstraintSecurityHandler; +import org.eclipse.jetty.security.HashLoginService; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.webapp.WebAppContext; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.keycloak.KeycloakSecurityContext; +import org.keycloak.OAuth2Constants; +import org.keycloak.adapters.jetty.AbstractKeycloakJettyAuthenticator; +import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.oidc.OpenIDConnectService; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.services.managers.RealmManager; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.rule.AbstractKeycloakRule; +import org.keycloak.testsuite.rule.WebResource; +import org.keycloak.testsuite.rule.WebRule; +import org.keycloak.testutils.KeycloakServer; +import org.openqa.selenium.WebDriver; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.io.OutputStream; +import java.security.Principal; + +/** + * @author Stian Thorgersen + */ +public class Jetty9Test { + static String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth")) + .queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString(); + + @ClassRule + public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() { + @Override + protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) { + RealmRepresentation representation = KeycloakServer.loadJson(getClass().getResourceAsStream("/jetty-test/demorealm.json"), RealmRepresentation.class); + RealmModel realm = manager.importRealm(representation); + } + }; + + public static class SendUsernameServlet extends HttpServlet { + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + if (req.getPathInfo().endsWith("logout")) { + req.logout(); + resp.setContentType("text/plain"); + OutputStream stream = resp.getOutputStream(); + stream.write("logout".getBytes()); + return; + + } + resp.setContentType("text/plain"); + OutputStream stream = resp.getOutputStream(); + Principal principal = req.getUserPrincipal(); + if (principal == null) { + stream.write("null".getBytes()); + return; + } + String name = principal.getName(); + stream.write(name.getBytes()); + stream.write("\n".getBytes()); + KeycloakSecurityContext context = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName()); + stream.write(context.getIdToken().getName().getBytes()); + stream.write("\n".getBytes()); + stream.write(logoutUri.getBytes()); + + } + @Override + protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + doGet(req, resp); + } + } + + public static Server server = null; + protected static WebAppContext appContext = null; + + + protected static void deploySP() throws Exception { + appContext = new WebAppContext(); + appContext.setResourceBase(Jetty9Test.class.getClassLoader().getResource("jetty-test/webapp").toExternalForm()); + appContext.setContextPath("/customer-portal"); + appContext.setParentLoaderPriority(true); + + appContext.addServlet(new ServletHolder(new SendUsernameServlet()), "/*"); + + + ConstraintSecurityHandler securityHandler = formHandler(); + + AbstractKeycloakJettyAuthenticator authenticator = new KeycloakJettyAuthenticator(); + securityHandler.setAuthenticator(authenticator); + + appContext.setSecurityHandler(securityHandler); + } + + private static ConstraintSecurityHandler formHandler() { + Constraint constraint = new Constraint(); + constraint.setName(Constraint.__FORM_AUTH); + ; + constraint.setRoles(new String[] { "user", "admin" }); + constraint.setAuthenticate(true); + + ConstraintMapping constraintMapping = new ConstraintMapping(); + constraintMapping.setConstraint(constraint); + constraintMapping.setPathSpec("/*"); + + ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); + securityHandler.setConstraintMappings(new ConstraintMapping[] { constraintMapping }); + + HashLoginService loginService = new HashLoginService(); + securityHandler.setLoginService(loginService); + return securityHandler; + } + + + + @BeforeClass + public static void initJetty() throws Exception { + server = new Server(8080); + + deploySP(); + + HandlerCollection handlers = new HandlerCollection(); + handlers.setHandlers(new Handler[] { appContext }); + server.setHandler(handlers); + + server.start(); + } + + + + @AfterClass + public static void shutdownJetty() throws Exception { + server.stop(); + server.destroy(); + } + + @Rule + public WebRule webRule = new WebRule(this); + @WebResource + protected WebDriver driver; + @WebResource + protected LoginPage loginPage; + + public static final String LOGIN_URL = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString(); + @Test + public void testLoginSSOAndLogout() throws Exception { + driver.navigate().to("http://localhost:8080/customer-portal"); + System.out.println("Current url: " + driver.getCurrentUrl()); + Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL)); + loginPage.login("bburke@redhat.com", "password"); + System.out.println("Current url: " + driver.getCurrentUrl()); + Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8080/customer-portal/"); + String pageSource = driver.getPageSource(); + System.out.println(pageSource); + Assert.assertTrue(pageSource.contains("Bill Burke")); + + // test logout + + String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth")) + .queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString(); + driver.navigate().to(logoutUri); + Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL)); + driver.navigate().to("http://localhost:8080/customer-portal"); + String currentUrl = driver.getCurrentUrl(); + Assert.assertTrue(currentUrl.startsWith(LOGIN_URL)); + + // test servletRequest.logout() + loginPage.login("bburke@redhat.com", "password"); + System.out.println("Current url: " + driver.getCurrentUrl()); + Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8080/customer-portal/"); + pageSource = driver.getPageSource(); + System.out.println(pageSource); + Assert.assertTrue(pageSource.contains("Bill Burke")); + driver.navigate().to("http://localhost:8080/customer-portal/logout"); + pageSource = driver.getPageSource(); + Assert.assertTrue(pageSource.contains("logout")); + driver.navigate().to("http://localhost:8080/customer-portal"); + currentUrl = driver.getCurrentUrl(); + Assert.assertTrue(currentUrl.startsWith(LOGIN_URL)); + + + } + + @Test + @Ignore + public void runit() throws Exception { + Thread.sleep(10000000); + } +} diff --git a/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json b/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json new file mode 100755 index 0000000000..a4a6ec9903 --- /dev/null +++ b/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json @@ -0,0 +1,58 @@ +{ + "id": "demo", + "realm": "demo", + "enabled": true, + "accessTokenLifespan": 3000, + "accessCodeLifespan": 10, + "accessCodeLifespanUserAction": 6000, + "sslRequired": "external", + "registrationAllowed": false, + "social": false, + "passwordCredentialGrantAllowed": true, + "updateProfileOnInitialSocialLogin": false, + "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", + "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "requiredCredentials": [ "password" ], + "users" : [ + { + "username" : "bburke@redhat.com", + "enabled": true, + "email" : "bburke@redhat.com", + "firstName": "Bill", + "lastName": "Burke", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "realmRoles": [ "user", "admin" ], + "applicationRoles": { + "account": [ "manage-account" ] + } + } + ], + "roles" : { + "realm" : [ + { + "name": "user", + "description": "User privileges" + }, + { + "name": "admin", + "description": "Administrator privileges" + } + ] + }, + "applications": [ + { + "name": "customer-portal", + "enabled": true, + "fullScopeAllowed": true, + "adminUrl": "http://localhost:8080/customer-portal", + "baseUrl": "http://localhost:8080/customer-portal", + "redirectUris": [ + "http://localhost:8080/customer-portal/*" + ], + "secret": "password" + } + ] +} diff --git a/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json b/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json new file mode 100755 index 0000000000..4e2fe1e556 --- /dev/null +++ b/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json @@ -0,0 +1,10 @@ +{ + "realm": "demo", + "resource": "customer-portal", + "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "auth-server-url": "http://localhost:8081/auth", + "ssl-required" : "external", + "credentials": { + "secret": "password" + } +} diff --git a/testsuite/pom.xml b/testsuite/pom.xml index 1e0b788b7f..3039f75c96 100755 --- a/testsuite/pom.xml +++ b/testsuite/pom.xml @@ -27,6 +27,7 @@ integration tomcat7 + jetty/jetty81 jetty/jetty92 jetty/jetty91 performance