Merge pull request #859 from patriot1burke/master

tomcat6
This commit is contained in:
Bill Burke 2014-11-15 12:00:18 -05:00
commit 7244e2f173
32 changed files with 1272 additions and 86 deletions

View file

@ -1,4 +1,4 @@
package org.keycloak.services.util; package org.keycloak.util;
import java.io.Serializable; import java.io.Serializable;
import java.text.DateFormat; import java.text.DateFormat;

View file

@ -80,6 +80,7 @@
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include> <include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include> <include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include> <include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat6-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include> <include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat8-adapter-dist:zip</include> <include>org.keycloak:keycloak-tomcat8-adapter-dist:zip</include>
<include>org.keycloak:keycloak-jetty81-adapter-dist:zip</include> <include>org.keycloak:keycloak-jetty81-adapter-dist:zip</include>

View file

@ -26,6 +26,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<type>zip</type> <type>zip</type>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat7-adapter-dist</artifactId> <artifactId>keycloak-tomcat7-adapter-dist</artifactId>

View file

@ -27,6 +27,7 @@
<modules> <modules>
<module>modules</module> <module>modules</module>
<module>as7-adapter-zip</module> <module>as7-adapter-zip</module>
<module>tomcat6-adapter-zip</module>
<module>tomcat7-adapter-zip</module> <module>tomcat7-adapter-zip</module>
<module>tomcat8-adapter-zip</module> <module>tomcat8-adapter-zip</module>
<module>eap6-adapter-zip</module> <module>eap6-adapter-zip</module>

View file

@ -0,0 +1,23 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-tomcat6-adapter</include>
</includes>
<excludes>
<exclude>org.apache.tomcat:catalina</exclude>
</excludes>
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,53 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.1.0.Beta2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak Tomcat 6 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat6-adapter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -31,6 +31,7 @@
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include> <include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include> <include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include> <include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat6-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include> <include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include>
<include>org.keycloak:keycloak-tomcat8-adapter-dist:zip</include> <include>org.keycloak:keycloak-tomcat8-adapter-dist:zip</include>
<include>org.keycloak:keycloak-jetty81-adapter-dist:zip</include> <include>org.keycloak:keycloak-jetty81-adapter-dist:zip</include>

View file

@ -26,6 +26,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<type>zip</type> <type>zip</type>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat7-adapter-dist</artifactId> <artifactId>keycloak-tomcat7-adapter-dist</artifactId>

View file

@ -1,14 +1,14 @@
<section id="tomcat-adapter"> <section id="tomcat-adapter">
<title>Tomcat 7 and 8 Adapter</title> <title>Tomcat 6, 7 and 8 Adapters</title>
<para> <para>
To be able to secure WAR apps deployed on Tomcat 7 and 8 you must install the Keycloak Tomcat 7 or 8 adapter To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 adapter
into your Tomcat installation. You then have to provide some extra configuration in each WAR you deploy to into your Tomcat installation. You then have to provide some extra configuration in each WAR you deploy to
Tomcat. Let's go over these steps. Tomcat. Let's go over these steps.
</para> </para>
<section id="tomcat-adapter-installation"> <section id="tomcat-adapter-installation">
<title>Adapter Installation</title> <title>Adapter Installation</title>
<para> <para>
There is a adapter zip file for Tomcat 7/8 in the <literal>adapters/</literal> directory in the Keycloak appliance There is a adapter zip file for Tomcat in the <literal>adapters/</literal> directory in the Keycloak appliance
or war distribution. You must unzip this file into Tomcat's <literal>lib/</literal> directory. Including or war distribution. You must unzip this file into Tomcat's <literal>lib/</literal> directory. Including
adapter's jars within your WEB-INF/lib directory will not work! The Keycloak adapter is implemented as a Valve adapter's jars within your WEB-INF/lib directory will not work! The Keycloak adapter is implemented as a Valve
and valve code must reside in Tomcat's main lib/ directory. and valve code must reside in Tomcat's main lib/ directory.
@ -16,6 +16,8 @@
<para> <para>
<programlisting> <programlisting>
$ cd $TOMCAT_HOME/lib $ cd $TOMCAT_HOME/lib
$ unzip keycloak-tomcat6-adapter-dist.zip
or
$ unzip keycloak-tomcat7-adapter-dist.zip $ unzip keycloak-tomcat7-adapter-dist.zip
or or
$ unzip keycloak-tomcat8-adapter-dist.zip $ unzip keycloak-tomcat8-adapter-dist.zip

View file

@ -15,6 +15,7 @@
<modules> <modules>
<module>tomcat-core</module> <module>tomcat-core</module>
<module>tomcat6</module>
<module>tomcat7</module> <module>tomcat7</module>
<module>tomcat8</module> <module>tomcat8</module>
</modules> </modules>

View file

@ -13,7 +13,8 @@
<name>Keycloak Tomcat Core Integration</name> <name>Keycloak Tomcat Core Integration</name>
<properties> <properties>
<!-- <tomcat.version>8.0.14</tomcat.version> --> <!-- <tomcat.version>8.0.14</tomcat.version> -->
<tomcat.version>7.0.52</tomcat.version> <!-- <tomcat.version>7.0.52</tomcat.version> -->
<tomcat.version>6.0.41</tomcat.version>
</properties> </properties>
<description /> <description />
@ -58,15 +59,17 @@
<groupId>org.codehaus.jackson</groupId> <groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId> <artifactId>jackson-xc</artifactId>
</dependency> </dependency>
<!--
<dependency> <dependency>
<groupId>org.apache.tomcat</groupId> <groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId> <artifactId>tomcat-servlet-api</artifactId>
<version>${tomcat.version}</version> <version>${tomcat.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
-->
<dependency> <dependency>
<groupId>org.apache.tomcat</groupId> <groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId> <artifactId>catalina</artifactId>
<version>${tomcat.version}</version> <version>${tomcat.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>

View file

@ -3,13 +3,11 @@ package org.keycloak.adapters.tomcat;
import org.apache.catalina.Context; import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle; import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener; import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Manager; import org.apache.catalina.Manager;
import org.apache.catalina.authenticator.FormAuthenticator; import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response; import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.constants.AdapterConstants; import org.keycloak.constants.AdapterConstants;
import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.AdapterDeploymentContext;
@ -55,13 +53,9 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
@Override @Override
public void lifecycleEvent(LifecycleEvent event) { public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.START_EVENT.equals(event.getType())) { if (Lifecycle.START_EVENT.equals(event.getType())) {
try { cache = false;
startDeployment();
} catch (LifecycleException e) {
log.severe("Error starting deployment. " + e.getMessage());
}
} else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) { } else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
initInternal(); keycloakInit();
} else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) { } else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
beforeStop(); beforeStop();
} }
@ -80,19 +74,11 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
tokenStore.logout(); tokenStore.logout();
request.removeAttribute(KeycloakSecurityContext.class.getName()); request.removeAttribute(KeycloakSecurityContext.class.getName());
} }
} request.setUserPrincipal(null);
public void startDeployment() throws LifecycleException {
super.start();
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
cache = false;
} }
@SuppressWarnings("UseSpecificCatch") @SuppressWarnings("UseSpecificCatch")
@Override public void keycloakInit() {
public void initInternal() {
// Possible scenarios: // Possible scenarios:
// 1) The deployment has a keycloak.config.resolver specified and it exists: // 1) The deployment has a keycloak.config.resolver specified and it exists:
// Outcome: adapter uses the resolver // Outcome: adapter uses the resolver
@ -182,6 +168,8 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
} }
} }
protected abstract GenericPrincipalFactory createPrincipalFactory();
protected boolean authenticateInternal(Request request, HttpServletResponse response) { protected boolean authenticateInternal(Request request, HttpServletResponse response) {
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
@ -192,7 +180,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
nodesRegistrationManagement.tryRegister(deployment); nodesRegistrationManagement.tryRegister(deployment);
CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, tokenStore, facade, request); CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, tokenStore, facade, request, createPrincipalFactory());
AuthOutcome outcome = authenticator.authenticate(); AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) { if (outcome == AuthOutcome.AUTHENTICATED) {
if (facade.isEnded()) { if (facade.isEnded()) {
@ -237,9 +225,9 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
} }
if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) { if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
store = new CatalinaSessionTokenStore(request, resolvedDeployment, userSessionManagement); store = new CatalinaSessionTokenStore(request, resolvedDeployment, userSessionManagement, createPrincipalFactory());
} else { } else {
store = new CatalinaCookieTokenStore(request, facade, resolvedDeployment); store = new CatalinaCookieTokenStore(request, facade, resolvedDeployment, createPrincipalFactory());
} }
request.setNote(TOKEN_STORE_NOTE, store); request.setNote(TOKEN_STORE_NOTE, store);

View file

@ -26,13 +26,15 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore {
private Request request; private Request request;
private HttpFacade facade; private HttpFacade facade;
private KeycloakDeployment deployment; private KeycloakDeployment deployment;
private GenericPrincipalFactory principalFactory;
private KeycloakPrincipal<RefreshableKeycloakSecurityContext> authenticatedPrincipal; private KeycloakPrincipal<RefreshableKeycloakSecurityContext> authenticatedPrincipal;
public CatalinaCookieTokenStore(Request request, HttpFacade facade, KeycloakDeployment deployment) { public CatalinaCookieTokenStore(Request request, HttpFacade facade, KeycloakDeployment deployment, GenericPrincipalFactory principalFactory) {
this.request = request; this.request = request;
this.facade = facade; this.facade = facade;
this.deployment = deployment; this.deployment = deployment;
this.principalFactory = principalFactory;
} }
@ -55,7 +57,7 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore {
securityContext.setCurrentRequestInfo(deployment, this); securityContext.setCurrentRequestInfo(deployment, this);
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext); Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles, securityContext); GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles, securityContext);
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
request.setUserPrincipal(principal); request.setUserPrincipal(principal);

View file

@ -2,6 +2,7 @@ package org.keycloak.adapters.tomcat;
import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.HttpFacade;
import org.keycloak.util.ServerCookie;
import javax.security.cert.X509Certificate; import javax.security.cert.X509Certificate;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -117,13 +118,10 @@ public class CatalinaHttpFacade implements HttpFacade {
@Override @Override
public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) { 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); StringBuffer cookieBuf = new StringBuffer();
if (domain != null) cookie.setDomain(domain); ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, null, maxAge, secure, httpOnly);
if (path != null) cookie.setPath(path); String cookie = cookieBuf.toString();
if (secure) cookie.setSecure(true); response.addHeader("Set-Cookie", cookie);
if (httpOnly) cookie.setHttpOnly(httpOnly);
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
} }
@Override @Override

View file

@ -29,11 +29,13 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
private static final Logger log = Logger.getLogger(""+CatalinaRequestAuthenticator.class); private static final Logger log = Logger.getLogger(""+CatalinaRequestAuthenticator.class);
protected AbstractKeycloakAuthenticatorValve valve; protected AbstractKeycloakAuthenticatorValve valve;
protected Request request; protected Request request;
protected GenericPrincipalFactory principalFactory;
public CatalinaRequestAuthenticator(KeycloakDeployment deployment, public CatalinaRequestAuthenticator(KeycloakDeployment deployment,
AbstractKeycloakAuthenticatorValve valve, AdapterTokenStore tokenStore, AbstractKeycloakAuthenticatorValve valve, AdapterTokenStore tokenStore,
CatalinaHttpFacade facade, CatalinaHttpFacade facade,
Request request) { Request request,
GenericPrincipalFactory principalFactory) {
super(facade, deployment, tokenStore, request.getConnector().getRedirectPort()); super(facade, deployment, tokenStore, request.getConnector().getRedirectPort());
this.valve = valve; this.valve = valve;
this.request = request; this.request = request;
@ -90,7 +92,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
if (log.isLoggable(Level.FINE)) { if (log.isLoggable(Level.FINE)) {
log.fine("Completing bearer authentication. Bearer roles: " + roles); log.fine("Completing bearer authentication. Bearer roles: " + roles);
} }
Principal generalPrincipal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), principal, roles, securityContext); Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
request.setUserPrincipal(generalPrincipal); request.setUserPrincipal(generalPrincipal);
request.setAuthType("KEYCLOAK"); request.setAuthType("KEYCLOAK");
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext); request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);

View file

@ -23,11 +23,13 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore {
private Request request; private Request request;
private KeycloakDeployment deployment; private KeycloakDeployment deployment;
private CatalinaUserSessionManagement sessionManagement; private CatalinaUserSessionManagement sessionManagement;
protected GenericPrincipalFactory principalFactory;
public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment, CatalinaUserSessionManagement sessionManagement) { public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment, CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory) {
this.request = request; this.request = request;
this.deployment = deployment; this.deployment = deployment;
this.sessionManagement = sessionManagement; this.sessionManagement = sessionManagement;
this.principalFactory = principalFactory;
} }
@Override @Override
@ -87,7 +89,7 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore {
public void saveAccountInfo(KeycloakAccount account) { public void saveAccountInfo(KeycloakAccount account) {
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext(); RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
Set<String> roles = account.getRoles(); Set<String> roles = account.getRoles();
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext); GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext);
Session session = request.getSessionInternal(true); Session session = request.getSessionInternal(true);
session.setPrincipal(principal); session.setPrincipal(principal);

View file

@ -18,24 +18,9 @@ import java.util.Set;
* @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a> * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class CatalinaSecurityContextHelper { public abstract class GenericPrincipalFactory {
public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) { public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
// KeycloakAccount account = new KeycloakAccount() {
// @Override
// public Principal getPrincipal() {
// return identity;
// }
//
// @Override
// public Set<String> getRoles() {
// return roleSet;
// }
//
// @Override
// public KeycloakSecurityContext getKeycloakSecurityContext() {
// return securityContext;
// }
// };
Subject subject = new Subject(); Subject subject = new Subject();
Set<Principal> principals = subject.getPrincipals(); Set<Principal> principals = subject.getPrincipals();
principals.add(identity); principals.add(identity);
@ -44,14 +29,6 @@ public class CatalinaSecurityContextHelper {
Group group = roleSets[g]; Group group = roleSets[g];
String name = group.getName(); String name = group.getName();
Group subjectGroup = createGroup(name, principals); Group subjectGroup = createGroup(name, principals);
// if (subjectGroup instanceof NestableGroup) {
// /* A NestableGroup only allows Groups to be added to it so we
// need to add a SimpleGroup to subjectRoles to contain the roles
// */
// SimpleGroup tmp = new SimpleGroup("Roles");
// subjectGroup.addMember(tmp);
// subjectGroup = tmp;
// }
// Copy the group members to the Subject group // Copy the group members to the Subject group
Enumeration<? extends Principal> members = group.members(); Enumeration<? extends Principal> members = group.members();
while (members.hasMoreElements()) { while (members.hasMoreElements()) {
@ -60,23 +37,15 @@ public class CatalinaSecurityContextHelper {
} }
} }
// add the CallerPrincipal group if none has been added in getRoleSets
// Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
// callerGroup.addMember(identity);
// principals.add(callerGroup);
// SecurityContext sc = SecurityContextAssociation.getSecurityContext();
// Principal userPrincipal = getPrincipal(subject);
// sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
// List<String> rolesAsStringList = new ArrayList<String>();
// rolesAsStringList.addAll(roleSet);
//
Principal userPrincipal = getPrincipal(subject); Principal userPrincipal = getPrincipal(subject);
List<String> rolesAsStringList = new ArrayList<String>(); List<String> rolesAsStringList = new ArrayList<String>();
rolesAsStringList.addAll(roleSet); rolesAsStringList.addAll(roleSet);
GenericPrincipal principal = new GenericPrincipal(userPrincipal.getName(), null, rolesAsStringList, userPrincipal, null); GenericPrincipal principal = createPrincipal(userPrincipal, rolesAsStringList);
return principal; return principal;
} }
protected abstract GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles);
/** /**
* Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
* considered or the single subject inside the CallerPrincipal group. * considered or the single subject inside the CallerPrincipal group.

View file

@ -0,0 +1,104 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.1.0.Beta2-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-tomcat6-adapter</artifactId>
<name>Keycloak Tomcat 6 Integration</name>
<properties>
<tomcat.version>6.0.41</tomcat.version>
</properties>
<description />
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss.logging.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat-core-adapter</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${keycloak.apache.httpcomponents.version}</version>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,46 @@
package org.keycloak.adapters.tomcat;
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 javax.servlet.ServletException;
import java.security.Principal;
import java.util.List;
/**
* Keycloak authentication valve
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
@Override
public boolean authenticate(Request request, Response 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) throws ServletException {
logoutInternal(request);
}
@Override
protected GenericPrincipalFactory createPrincipalFactory() {
return new GenericPrincipalFactory() {
@Override
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
return new GenericPrincipal(null, userPrincipal.getName(), null, roles, userPrincipal, null);
}
};
}
}

View file

@ -37,6 +37,20 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat-core-adapter</artifactId> <artifactId>keycloak-tomcat-core-adapter</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>

View file

@ -1,11 +1,15 @@
package org.keycloak.adapters.tomcat; package org.keycloak.adapters.tomcat;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig; import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.security.Principal;
import java.util.List;
/** /**
* Keycloak authentication valve * Keycloak authentication valve
@ -14,14 +18,26 @@ import java.io.IOException;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve { public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException { public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
return authenticateInternal(request, response); return authenticateInternal(request, response);
} }
@Override protected void initInternal() {
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
public void logout(Request request) throws ServletException { public void logout(Request request) throws ServletException {
logoutInternal(request); logoutInternal(request);
super.logout(request); }
@Override
protected GenericPrincipalFactory createPrincipalFactory() {
return new GenericPrincipalFactory() {
@Override
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
}
};
} }
} }

View file

@ -45,6 +45,10 @@
<groupId>org.apache.tomcat</groupId> <groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId> <artifactId>tomcat-catalina</artifactId>
</exclusion> </exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
</exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -1,10 +1,14 @@
package org.keycloak.adapters.tomcat; package org.keycloak.adapters.tomcat;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.realm.GenericPrincipal;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.security.Principal;
import java.util.List;
/** /**
* Keycloak authentication valve * Keycloak authentication valve
@ -13,18 +17,26 @@ import java.io.IOException;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve { public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
@Override
public boolean authenticate(Request request, HttpServletResponse response) throws IOException { public boolean authenticate(Request request, HttpServletResponse response) throws IOException {
return authenticateInternal(request, response); return authenticateInternal(request, response);
} }
@Override protected void initInternal() {
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
public void logout(Request request) { public void logout(Request request) {
logoutInternal(request); logoutInternal(request);
try { }
super.logout(request);
} catch (Exception e) { @Override
throw new RuntimeException(e); protected GenericPrincipalFactory createPrincipalFactory() {
} return new GenericPrincipalFactory() {
@Override
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
}
};
} }
} }

View file

@ -2,6 +2,7 @@ package org.keycloak.services.util;
import org.jboss.resteasy.spi.HttpResponse; import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.util.ServerCookie;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;

View file

@ -26,6 +26,7 @@
</build> </build>
<modules> <modules>
<module>integration</module> <module>integration</module>
<module>tomcat6</module>
<module>tomcat7</module> <module>tomcat7</module>
<module>tomcat8</module> <module>tomcat8</module>
<module>jetty/jetty81</module> <module>jetty/jetty81</module>

501
testsuite/tomcat6/pom.xml Executable file
View file

@ -0,0 +1,501 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-testsuite-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>1.1.0.Beta2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-testsuite-tomcat6</artifactId>
<name>Keycloak Tomcat 6 Integration TestSuite</name>
<properties>
<tomcat.version>6.0.41</tomcat.version>
</properties>
<description />
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-dependencies-server-all</artifactId>
<version>${project.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>${resteasy.version.latest}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-crypto</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-undertow</artifactId>
<version>${resteasy.version.latest}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${keycloak.apache.httpcomponents.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-ldap-federation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-undertow-adapter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat6-adapter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-undertow</artifactId>
<version>${wildfly.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-testsuite-integration</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-testsuite-integration</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>coyote</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<workingDirectory>${project.basedir}</workingDirectory>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>keycloak-server</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>org.keycloak.testutils.KeycloakServer</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>mail-server</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>org.keycloak.testutils.MailServer</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>totp</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>org.keycloak.testutils.TotpGenerator</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>jpa</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<keycloak.realm.provider>jpa</keycloak.realm.provider>
<keycloak.user.provider>jpa</keycloak.user.provider>
<keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
<keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>mongo</id>
<properties>
<keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
<keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
<keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
<keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
<keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
</properties>
<build>
<plugins>
<!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<keycloak.realm.provider>mongo</keycloak.realm.provider>
<keycloak.user.provider>mongo</keycloak.user.provider>
<keycloak.audit.provider>mongo</keycloak.audit.provider>
<keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
<keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
<keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
<keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
<keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
<keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
</systemPropertyVariables>
</configuration>
</execution>
<execution>
<id>default-test</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
<!-- Embedded mongo -->
<plugin>
<groupId>com.github.joelittlejohn.embedmongo</groupId>
<artifactId>embedmongo-maven-plugin</artifactId>
<executions>
<execution>
<id>start-mongodb</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<port>${keycloak.connectionsMongo.port}</port>
<logging>file</logging>
<logFile>${project.build.directory}/mongodb.log</logFile>
<bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
</configuration>
</execution>
<execution>
<id>stop-mongodb</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>infinispan</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
<keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
<keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- MySQL -->
<profile>
<activation>
<property>
<name>keycloak.connectionsJpa.driver</name>
<value>com.mysql.jdbc.Driver</value>
</property>
</activation>
<id>mysql</id>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</profile>
<!-- PostgreSQL -->
<profile>
<activation>
<property>
<name>keycloak.connectionsJpa.driver</name>
<value>org.postgresql.Driver</value>
</property>
</activation>
<id>postgresql</id>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>clean-jpa</id>
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<configuration>
<changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
<url>${keycloak.connectionsJpa.url}</url>
<driver>${keycloak.connectionsJpa.driver}</driver>
<username>${keycloak.connectionsJpa.user}</username>
<password>${keycloak.connectionsJpa.password}</password>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
<executions>
<execution>
<id>clean-jpa</id>
<phase>clean</phase>
<goals>
<goal>dropAll</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View file

@ -0,0 +1,131 @@
package org.keycloak.testsuite;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Embedded;
import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TomcatServer {
private Embedded server;
private int port;
private boolean isRunning;
private static final Logger LOG = LoggerFactory.getLogger(TomcatServer.class);
private static final boolean isInfo = LOG.isInfoEnabled();
/**
* Create a new Tomcat embedded server instance. Setup looks like:
* <pre><Server>
* <Service>
* <Connector />
* <Engine&gt
* <Host>
* <Context />
* </Host>
* </Engine>
* </Service>
* </Server></pre>
* <Server> & <Service> will be created automcatically. We need to hook the remaining to an {@link Embedded} instnace
*
* @param contextPath Context path for the application
* @param port Port number to be used for the embedded Tomcat server
* @param appBase Path to the Application files (for Maven based web apps, in general: <code>/src/main/</code>)
* @param shutdownHook If true, registers a server' shutdown hook with JVM. This is useful to shutdown the server
* in erroneous cases.
* @throws Exception
*/
public TomcatServer(String contextPath, int port, String appBase, boolean shutdownHook) {
if (contextPath == null || appBase == null || appBase.length() == 0) {
throw new IllegalArgumentException("Context path or appbase should not be null");
}
if (!contextPath.startsWith("/")) {
contextPath = "/" + contextPath;
}
this.port = port;
server = new Embedded();
server.setName("TomcatEmbeddedServer");
Host localHost = server.createHost("localhost", appBase);
localHost.setAutoDeploy(false);
StandardContext rootContext = (StandardContext) server.createContext(contextPath, "webapp");
KeycloakAuthenticatorValve valve = new KeycloakAuthenticatorValve();
rootContext.addValve(valve);
//rootContext.addLifecycleListener(valve);
rootContext.setDefaultWebXml("web.xml");
localHost.addChild(rootContext);
Engine engine = server.createEngine();
engine.setDefaultHost(localHost.getName());
engine.setName("TomcatEngine");
engine.addChild(localHost);
server.addEngine(engine);
Connector connector = server.createConnector(localHost.getName(), port, false);
server.addConnector(connector);
// register shutdown hook
if (shutdownHook) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
if (isRunning) {
if (isInfo) LOG.info("Stopping the Tomcat server, through shutdown hook");
try {
if (server != null) {
server.stop();
}
} catch (LifecycleException e) {
LOG.error("Error while stopping the Tomcat server, through shutdown hook", e);
}
}
}
});
}
}
/**
* Start the tomcat embedded server
*/
public void start() throws LifecycleException {
if (isRunning) {
LOG.warn("Tomcat server is already running @ port={}; ignoring the start", port);
return;
}
if (isInfo) LOG.info("Starting the Tomcat server @ port={}", port);
server.setAwait(true);
server.start();
isRunning = true;
}
/**
* Stop the tomcat embedded server
*/
public void stop() throws LifecycleException {
if (!isRunning) {
LOG.warn("Tomcat server is not running @ port={}", port);
return;
}
if (isInfo) LOG.info("Stopping the Tomcat server");
server.stop();
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
}

View file

@ -0,0 +1,187 @@
/*
* 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.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.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.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.security.Principal;
import java.util.regex.Matcher;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class TomcatTest {
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("/tomcat-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 {
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);
}
}
static TomcatServer tomcat = null;
@BeforeClass
public static void initTomcat() throws Exception {
URL dir = TomcatTest.class.getResource("/tomcat-test/webapp/META-INF/context.xml");
String baseDir = new File(dir.getFile()).getParentFile().getParentFile().getParentFile().toString();
System.out.println("Tomcat basedir: " + baseDir);
tomcat = new TomcatServer("/customer-portal", 8080, baseDir, false);
tomcat.start();
//tomcat.getServer().await();
}
@AfterClass
public static void shutdownTomcat() throws Exception {
tomcat.stop();
}
@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();
@Ignore
@Test
public void testServer() throws Exception{
Thread.sleep(1000000000);
}
@Test
public void testLoginSSOAndLogout() throws Exception {
driver.navigate().to("http://localhost:8080/customer-portal");
System.out.println("Current url: " + driver.getCurrentUrl());
//System.out.println(driver.getPageSource());
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
@Ignore
public void runit() throws Exception {
Thread.sleep(10000000);
}
private static String getBaseDirectory() {
String dirPath = null;
String relativeDirPath = "testsuite" + File.separator + "tomcat6" + File.separator + "target";
if (System.getProperties().containsKey("maven.home")) {
dirPath = System.getProperty("user.dir").replaceFirst("testsuite.tomcat6.*", Matcher.quoteReplacement(relativeDirPath));
} else {
for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
if (c.contains(File.separator + "testsuite" + File.separator + "tomcat6")) {
dirPath = c.replaceFirst("testsuite.tomcat6.*", Matcher.quoteReplacement(relativeDirPath));
break;
}
}
}
String absolutePath = new File(dirPath).getAbsolutePath();
return absolutePath;
}
}

View file

@ -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"
}
]
}

View file

@ -0,0 +1,3 @@
<Context path="/customer-portal">
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
</Context>

View file

@ -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"
}
}

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<module-name>adapter-test</module-name>
<servlet>
<servlet-name>SendUsername</servlet-name>
<servlet-class>org.keycloak.testsuite.TomcatTest$SendUsernameServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SendUsername</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admins</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>demo</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>