more jetty adapter
This commit is contained in:
parent
31050e0580
commit
3805510e20
10 changed files with 232 additions and 72 deletions
33
distribution/jetty9-adapter-zip/assembly.xml
Executable file
33
distribution/jetty9-adapter-zip/assembly.xml
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
<assembly>
|
||||||
|
<id>war-dist</id>
|
||||||
|
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory></directory>
|
||||||
|
<includes>
|
||||||
|
<include>keycloak.mod</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>modules</outputDirectory>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/modules</directory>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<unpack>false</unpack>
|
||||||
|
<useTransitiveDependencies>true</useTransitiveDependencies>
|
||||||
|
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||||
|
<includes>
|
||||||
|
<include>org.keycloak:keycloak-jetty9-adapter</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>lib/keycloak</outputDirectory>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
</assembly>
|
11
distribution/jetty9-adapter-zip/keycloak.mod
Executable file
11
distribution/jetty9-adapter-zip/keycloak.mod
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#
|
||||||
|
# Keycloak Jetty Adapter
|
||||||
|
#
|
||||||
|
|
||||||
|
[depend]
|
||||||
|
server
|
||||||
|
security
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
lib/keycloak/*.jar
|
||||||
|
|
53
distribution/jetty9-adapter-zip/pom.xml
Executable file
53
distribution/jetty9-adapter-zip/pom.xml
Executable 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-jetty9-adapter-dist</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Keycloak Jetty 9 Adapter Distro</name>
|
||||||
|
<description/>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-jetty9-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>
|
|
@ -12,7 +12,7 @@
|
||||||
<artifactId>keycloak-jetty9-adapter</artifactId>
|
<artifactId>keycloak-jetty9-adapter</artifactId>
|
||||||
<name>Keycloak Jetty 9 Integration</name>
|
<name>Keycloak Jetty 9 Integration</name>
|
||||||
<properties>
|
<properties>
|
||||||
<jetty9.version>9.1.0.v20131115</jetty9.version>
|
<jetty9.version>9.2.4.v20141103</jetty9.version>
|
||||||
</properties>
|
</properties>
|
||||||
<description />
|
<description />
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
|
||||||
import org.keycloak.adapters.CookieTokenStore;
|
import org.keycloak.adapters.CookieTokenStore;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.KeycloakAccount;
|
||||||
|
@ -13,8 +12,6 @@ import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle storage of token info in cookie. Per-request object.
|
* Handle storage of token info in cookie. Per-request object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,7 +20,6 @@ import org.keycloak.enums.TokenStore;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -70,8 +69,9 @@ public class JettyRequestAuthenticator extends RequestAuthenticator {
|
||||||
if (MimeTypes.Type.FORM_ENCODED.is(request.getContentType()) && HttpMethod.POST.is(request.getMethod())) {
|
if (MimeTypes.Type.FORM_ENCODED.is(request.getContentType()) && HttpMethod.POST.is(request.getMethod())) {
|
||||||
Request base_request = (request instanceof Request) ? (Request) request : HttpChannel
|
Request base_request = (request instanceof Request) ? (Request) request : HttpChannel
|
||||||
.getCurrentHttpChannel().getRequest();
|
.getCurrentHttpChannel().getRequest();
|
||||||
base_request.extractParameters();
|
MultiMap<String> formParameters = new MultiMap<String>();
|
||||||
session.setAttribute(FormAuthenticator.__J_POST, new MultiMap<String>(base_request.getParameters()));
|
base_request.extractFormParameters(formParameters);
|
||||||
|
session.setAttribute(FormAuthenticator.__J_POST, formParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ public class JettyRequestAuthenticator extends RequestAuthenticator {
|
||||||
MultiMap<String> j_post = (MultiMap<String>) session.getAttribute(FormAuthenticator.__J_POST);
|
MultiMap<String> j_post = (MultiMap<String>) session.getAttribute(FormAuthenticator.__J_POST);
|
||||||
if (j_post != null) {
|
if (j_post != null) {
|
||||||
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest();
|
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest();
|
||||||
base_request.setParameters(j_post);
|
base_request.setContentParameters(j_post);
|
||||||
}
|
}
|
||||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||||
session.removeAttribute(FormAuthenticator.__J_METHOD);
|
session.removeAttribute(FormAuthenticator.__J_METHOD);
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle storage of token info in HTTP Session. Per-request object
|
* Handle storage of token info in HTTP Session. Per-request object
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
package org.keycloak.adapters.jetty;
|
package org.keycloak.adapters.jetty;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.security.Authenticator;
|
|
||||||
import org.eclipse.jetty.security.DefaultUserIdentity;
|
import org.eclipse.jetty.security.DefaultUserIdentity;
|
||||||
import org.eclipse.jetty.security.ServerAuthException;
|
import org.eclipse.jetty.security.ServerAuthException;
|
||||||
import org.eclipse.jetty.security.UserAuthentication;
|
import org.eclipse.jetty.security.UserAuthentication;
|
||||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
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.Authentication;
|
||||||
import org.eclipse.jetty.server.HttpChannel;
|
import org.eclipse.jetty.server.HttpChannel;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.UserIdentity;
|
import org.eclipse.jetty.server.UserIdentity;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterConstants;
|
import org.keycloak.adapters.AdapterConstants;
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
|
@ -30,89 +28,97 @@ import org.keycloak.adapters.NodesRegistrationManagement;
|
||||||
import org.keycloak.adapters.PreAuthActionsHandler;
|
import org.keycloak.adapters.PreAuthActionsHandler;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.enums.TokenStore;
|
import org.keycloak.enums.TokenStore;
|
||||||
|
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class KeycloakJettyAuthenticator extends FormAuthenticator {
|
public class KeycloakJettyAuthenticator extends LoginAuthenticator {
|
||||||
private static final org.jboss.logging.Logger log = Logger.getLogger(KeycloakJettyAuthenticator.class);
|
private static final org.jboss.logging.Logger log = Logger.getLogger(KeycloakJettyAuthenticator.class);
|
||||||
protected AdapterDeploymentContext deploymentContext;
|
protected AdapterDeploymentContext deploymentContext;
|
||||||
protected NodesRegistrationManagement nodesRegistrationManagement;
|
protected NodesRegistrationManagement nodesRegistrationManagement;
|
||||||
|
protected AdapterConfig adapterConfig;
|
||||||
|
protected KeycloakConfigResolver configResolver;
|
||||||
|
|
||||||
public KeycloakJettyAuthenticator() {
|
public KeycloakJettyAuthenticator() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakJettyAuthenticator(String login, String error, boolean dispatch) {
|
@Override
|
||||||
super(login, error, dispatch);
|
public void setConfiguration(AuthConfiguration configuration) {
|
||||||
|
//super.setConfiguration(configuration);
|
||||||
|
initializeKeycloak();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setConfiguration(AuthConfiguration configuration) {
|
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException
|
||||||
super.setConfiguration(configuration);
|
{
|
||||||
initializeKeycloak();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdapterConfig getAdapterConfig() {
|
||||||
|
return adapterConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdapterConfig(AdapterConfig adapterConfig) {
|
||||||
|
this.adapterConfig = adapterConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeycloakConfigResolver getConfigResolver() {
|
||||||
|
return configResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigResolver(KeycloakConfigResolver configResolver) {
|
||||||
|
this.configResolver = configResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UseSpecificCatch")
|
@SuppressWarnings("UseSpecificCatch")
|
||||||
public void initializeKeycloak() {
|
public void initializeKeycloak() {
|
||||||
|
nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||||
String contextPath = ContextHandler.getCurrentContext().getContextPath();
|
String contextPath = ContextHandler.getCurrentContext().getContextPath();
|
||||||
ServletContext theServletContext = ContextHandler.getCurrentContext().getContext(contextPath);
|
ServletContext theServletContext = ContextHandler.getCurrentContext().getContext(contextPath);
|
||||||
// Possible scenarios:
|
|
||||||
// 1) The deployment has a keycloak.config.resolver specified and it exists:
|
|
||||||
// Outcome: adapter uses the resolver
|
|
||||||
// 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
|
|
||||||
// Outcome: adapter is left unconfigured
|
|
||||||
// 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
|
|
||||||
// Outcome: adapter uses it
|
|
||||||
// 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
|
|
||||||
// Outcome: adapter is left unconfigured
|
|
||||||
|
|
||||||
String configResolverClass = theServletContext.getInitParameter("keycloak.config.resolver");
|
if (configResolver == null) {
|
||||||
if (configResolverClass != null) {
|
String configResolverClass = theServletContext.getInitParameter("keycloak.config.resolver");
|
||||||
try {
|
if (configResolverClass != null) {
|
||||||
KeycloakConfigResolver configResolver = (KeycloakConfigResolver) ContextHandler.getCurrentContext().getClassLoader().loadClass(configResolverClass).newInstance();
|
try {
|
||||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
configResolver = (KeycloakConfigResolver) ContextHandler.getCurrentContext().getClassLoader().loadClass(configResolverClass).newInstance();
|
||||||
log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.infov("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
|
log.infov("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
|
||||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
InputStream configInputStream = getConfigInputStream(theServletContext);
|
|
||||||
KeycloakDeployment kd;
|
|
||||||
if (configInputStream == null) {
|
|
||||||
log.debug("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
|
||||||
kd = new KeycloakDeployment();
|
|
||||||
} else {
|
|
||||||
kd = KeycloakDeploymentBuilder.build(configInputStream);
|
|
||||||
}
|
|
||||||
deploymentContext = new AdapterDeploymentContext(kd);
|
|
||||||
log.debug("Keycloak is using a per-deployment configuration.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
if (configResolver != null) {
|
||||||
//AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||||
//setNext(actions);
|
} else if (adapterConfig != null) {
|
||||||
|
KeycloakDeployment kd = KeycloakDeploymentBuilder.build(adapterConfig);
|
||||||
|
deploymentContext = new AdapterDeploymentContext(kd);
|
||||||
|
} else {
|
||||||
|
InputStream configInputStream = getConfigInputStream(theServletContext);
|
||||||
|
if (configInputStream == null) {
|
||||||
|
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||||
|
|
||||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
} else {
|
||||||
|
deploymentContext = new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(configInputStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InputStream getJSONFromServletContext(ServletContext servletContext) {
|
private static InputStream getJSONFromServletContext(ServletContext servletContext) {
|
||||||
|
@ -146,6 +152,8 @@ public class KeycloakJettyAuthenticator extends FormAuthenticator {
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
log.trace("*** authenticate");
|
log.trace("*** authenticate");
|
||||||
}
|
}
|
||||||
|
if (!mandatory)
|
||||||
|
return new DeferredAuthentication(this);
|
||||||
Request request = HttpChannel.getCurrentHttpChannel().getRequest();
|
Request request = HttpChannel.getCurrentHttpChannel().getRequest();
|
||||||
JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse)res);
|
JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse)res);
|
||||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||||
|
@ -189,7 +197,7 @@ public class KeycloakJettyAuthenticator extends FormAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
||||||
protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
public static AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
||||||
AdapterTokenStore store = (AdapterTokenStore)request.getAttribute(TOKEN_STORE_NOTE);
|
AdapterTokenStore store = (AdapterTokenStore)request.getAttribute(TOKEN_STORE_NOTE);
|
||||||
if (store != null) {
|
if (store != null) {
|
||||||
return store;
|
return store;
|
||||||
|
@ -205,24 +213,61 @@ public class KeycloakJettyAuthenticator extends FormAuthenticator {
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Authentication register(HttpServletRequest httpServletRequest, KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
|
public static class KeycloakAuthentication extends UserAuthentication
|
||||||
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(principal.getKeycloakSecurityContext());
|
{
|
||||||
if (roles == null) {
|
public KeycloakAuthentication(String method, UserIdentity userIdentity) {
|
||||||
roles = new HashSet<String>();
|
super(method, userIdentity);
|
||||||
}
|
}
|
||||||
Request request = (Request) httpServletRequest;
|
|
||||||
Authentication authentication = request.getAuthentication();
|
|
||||||
if (!(authentication instanceof UserAuthentication)) {
|
|
||||||
Subject theSubject = new Subject();
|
|
||||||
String[] theRoles = new String[roles.size()];
|
|
||||||
roles.toArray(theRoles);
|
|
||||||
|
|
||||||
UserIdentity userIdentity = new DefaultUserIdentity(theSubject, principal, theRoles);
|
@Override
|
||||||
authentication = new UserAuthentication(getAuthMethod(), userIdentity);
|
public void logout() {
|
||||||
|
Request request = HttpChannel.getCurrentHttpChannel().getRequest();
|
||||||
|
logoutCurrent(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logoutCurrent(Request request) {
|
||||||
|
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext)request.getAttribute(AdapterDeploymentContext.class.getName());
|
||||||
|
KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||||
|
if (ksc != null) {
|
||||||
|
JettyHttpFacade facade = new JettyHttpFacade(request, null);
|
||||||
|
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||||
|
if (ksc instanceof RefreshableKeycloakSecurityContext) {
|
||||||
|
((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
|
||||||
|
tokenStore.logout();
|
||||||
|
request.removeAttribute(KeycloakSecurityContext.class.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Authentication register(Request request, KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
|
||||||
|
request.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||||
|
Authentication authentication = request.getAuthentication();
|
||||||
|
if (!(authentication instanceof KeycloakAuthentication)) {
|
||||||
|
UserIdentity userIdentity = createIdentity(principal);
|
||||||
|
authentication = new KeycloakAuthentication(getAuthMethod(), userIdentity);
|
||||||
request.setAuthentication(authentication);
|
request.setAuthentication(authentication);
|
||||||
}
|
}
|
||||||
return authentication;
|
return authentication;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UserIdentity createIdentity(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
|
||||||
|
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(principal.getKeycloakSecurityContext());
|
||||||
|
if (roles == null) {
|
||||||
|
roles = new HashSet<String>();
|
||||||
|
}
|
||||||
|
Subject theSubject = new Subject();
|
||||||
|
String[] theRoles = new String[roles.size()];
|
||||||
|
roles.toArray(theRoles);
|
||||||
|
|
||||||
|
return new DefaultUserIdentity(theSubject, principal, theRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<artifactId>keycloak-testsuite-jetty9</artifactId>
|
<artifactId>keycloak-testsuite-jetty9</artifactId>
|
||||||
<name>Keycloak Jetty 9 Integration TestSuite</name>
|
<name>Keycloak Jetty 9 Integration TestSuite</name>
|
||||||
<properties>
|
<properties>
|
||||||
<jetty9.version>9.1.0.v20131115</jetty9.version>
|
<jetty9.version>9.2.4.v20141103</jetty9.version>
|
||||||
</properties>
|
</properties>
|
||||||
<description />
|
<description />
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,14 @@ public class Jetty9Test {
|
||||||
public static class SendUsernameServlet extends HttpServlet {
|
public static class SendUsernameServlet extends HttpServlet {
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
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");
|
resp.setContentType("text/plain");
|
||||||
OutputStream stream = resp.getOutputStream();
|
OutputStream stream = resp.getOutputStream();
|
||||||
Principal principal = req.getUserPrincipal();
|
Principal principal = req.getUserPrincipal();
|
||||||
|
@ -199,6 +207,20 @@ public class Jetty9Test {
|
||||||
String currentUrl = driver.getCurrentUrl();
|
String currentUrl = driver.getCurrentUrl();
|
||||||
Assert.assertTrue(currentUrl.startsWith(LOGIN_URL));
|
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));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue