Remove Jetty OIDC adapter
Closes #28779 Signed-off-by: Douglas Palmer <dpalmer@redhat.com>
This commit is contained in:
parent
c5dbab2740
commit
a4a7d023a7
23 changed files with 0 additions and 1916 deletions
|
@ -1,154 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<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>999.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-jetty-core</artifactId>
|
|
||||||
<name>Keycloak Jetty Core Integration</name>
|
|
||||||
<properties>
|
|
||||||
<keycloak.osgi.export>
|
|
||||||
org.keycloak.adapters.jetty.core.*
|
|
||||||
</keycloak.osgi.export>
|
|
||||||
<keycloak.osgi.import>
|
|
||||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
|
||||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
|
||||||
org.keycloak.*;version="${project.version}",
|
|
||||||
*;resolution:=optional
|
|
||||||
</keycloak.osgi.import>
|
|
||||||
</properties>
|
|
||||||
<description />
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>jboss-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>commons-logging-jboss-logging</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-adapter-spi</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-adapter-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpclient</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk18on</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-annotations</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-server</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-util</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-security</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>bundle-manifest</id>
|
|
||||||
<phase>process-classes</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>manifest</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<instructions>
|
|
||||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
|
||||||
<Bundle-Name>${project.name}</Bundle-Name>
|
|
||||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
|
||||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
|
||||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,356 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.core;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.security.DefaultUserIdentity;
|
|
||||||
import org.eclipse.jetty.security.IdentityService;
|
|
||||||
import org.eclipse.jetty.security.LoginService;
|
|
||||||
import org.eclipse.jetty.security.ServerAuthException;
|
|
||||||
import org.eclipse.jetty.security.UserAuthentication;
|
|
||||||
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
|
|
||||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
|
||||||
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
|
|
||||||
import org.eclipse.jetty.server.Authentication;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.UserIdentity;
|
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.KeycloakPrincipal;
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
|
||||||
import org.keycloak.adapters.AuthenticatedActionsHandler;
|
|
||||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
|
||||||
import org.keycloak.adapters.NodesRegistrationManagement;
|
|
||||||
import org.keycloak.adapters.PreAuthActionsHandler;
|
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
|
||||||
import org.keycloak.adapters.spi.AuthChallenge;
|
|
||||||
import org.keycloak.adapters.spi.AuthOutcome;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
import org.keycloak.constants.AdapterConstants;
|
|
||||||
import org.keycloak.enums.TokenStore;
|
|
||||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthenticator {
|
|
||||||
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
|
||||||
protected static final org.jboss.logging.Logger log = Logger.getLogger(AbstractKeycloakJettyAuthenticator.class);
|
|
||||||
protected AdapterDeploymentContext deploymentContext;
|
|
||||||
protected NodesRegistrationManagement nodesRegistrationManagement;
|
|
||||||
protected AdapterConfig adapterConfig;
|
|
||||||
protected KeycloakConfigResolver configResolver;
|
|
||||||
protected String errorPage;
|
|
||||||
|
|
||||||
public AbstractKeycloakJettyAuthenticator() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static InputStream getJSONFromServletContext(ServletContext servletContext) {
|
|
||||||
String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
|
|
||||||
if (json == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ByteArrayInputStream(json.getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
public AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
|
||||||
AdapterTokenStore store = (AdapterTokenStore) request.getAttribute(TOKEN_STORE_NOTE);
|
|
||||||
if (store != null) {
|
|
||||||
return store;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
|
|
||||||
store = createSessionTokenStore(request, resolvedDeployment);
|
|
||||||
} else {
|
|
||||||
store = new JettyCookieTokenStore(request, facade, resolvedDeployment);
|
|
||||||
}
|
|
||||||
|
|
||||||
request.setAttribute(TOKEN_STORE_NOTE, store);
|
|
||||||
return store;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
|
|
||||||
|
|
||||||
public abstract JettyUserSessionManagement createSessionManagement(Request request);
|
|
||||||
|
|
||||||
public 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 OIDCJettyHttpFacade(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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class DummyLoginService implements LoginService {
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserIdentity login(String username, Object credentials, ServletRequest var3) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validate(UserIdentity user) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IdentityService getIdentityService() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIdentityService(IdentityService service) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logout(UserIdentity user) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfiguration(AuthConfiguration configuration) {
|
|
||||||
//super.setConfiguration(configuration);
|
|
||||||
initializeKeycloak();
|
|
||||||
// need this so that getUserPrincipal does not throw NPE
|
|
||||||
_loginService = new DummyLoginService();
|
|
||||||
String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
|
|
||||||
setErrorPage(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setErrorPage(String path) {
|
|
||||||
if (path == null || path.trim().length() == 0) {
|
|
||||||
} else {
|
|
||||||
if (!path.startsWith("/")) {
|
|
||||||
path = "/" + path;
|
|
||||||
}
|
|
||||||
errorPage = path;
|
|
||||||
|
|
||||||
if (errorPage.indexOf('?') > 0)
|
|
||||||
errorPage = errorPage.substring(0, errorPage.indexOf('?'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException {
|
|
||||||
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")
|
|
||||||
public void initializeKeycloak() {
|
|
||||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
|
||||||
|
|
||||||
ServletContext theServletContext = null;
|
|
||||||
ContextHandler.Context currentContext = ContextHandler.getCurrentContext();
|
|
||||||
if (currentContext != null) {
|
|
||||||
String contextPath = currentContext.getContextPath();
|
|
||||||
|
|
||||||
if ("".equals(contextPath)) {
|
|
||||||
// This could be the case in osgi environment when deploying apps through pax whiteboard extension.
|
|
||||||
theServletContext = currentContext;
|
|
||||||
} else {
|
|
||||||
theServletContext = currentContext.getContext(contextPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jetty 9.1.x servlet context will be null :(
|
|
||||||
if (configResolver == null && theServletContext != null) {
|
|
||||||
String configResolverClass = theServletContext.getInitParameter("keycloak.config.resolver");
|
|
||||||
if (configResolverClass != null) {
|
|
||||||
try {
|
|
||||||
configResolver = (KeycloakConfigResolver) ContextHandler.getCurrentContext().getClassLoader().loadClass(configResolverClass).newInstance();
|
|
||||||
log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
|
||||||
} 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()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configResolver != null) {
|
|
||||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
|
||||||
} else if (adapterConfig != null) {
|
|
||||||
KeycloakDeployment kd = KeycloakDeploymentBuilder.build(adapterConfig);
|
|
||||||
deploymentContext = new AdapterDeploymentContext(kd);
|
|
||||||
} else if (theServletContext != null) {
|
|
||||||
InputStream configInputStream = getConfigInputStream(theServletContext);
|
|
||||||
if (configInputStream != null) {
|
|
||||||
deploymentContext = new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(configInputStream));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deploymentContext == null) {
|
|
||||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
|
||||||
}
|
|
||||||
if (theServletContext != null)
|
|
||||||
theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getConfigInputStream(ServletContext servletContext) {
|
|
||||||
InputStream is = getJSONFromServletContext(servletContext);
|
|
||||||
if (is == null) {
|
|
||||||
String path = servletContext.getInitParameter("keycloak.config.file");
|
|
||||||
if (path == null) {
|
|
||||||
is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
is = new FileInputStream(path);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException {
|
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.trace("*** authenticate");
|
|
||||||
}
|
|
||||||
Request request = resolveRequest(req);
|
|
||||||
OIDCJettyHttpFacade facade = new OIDCJettyHttpFacade(request, (HttpServletResponse) res);
|
|
||||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
|
||||||
if (deployment == null || !deployment.isConfigured()) {
|
|
||||||
log.debug("*** deployment isn't configured return false");
|
|
||||||
return Authentication.UNAUTHENTICATED;
|
|
||||||
}
|
|
||||||
PreAuthActionsHandler handler = new PreAuthActionsHandler(createSessionManagement(request), deploymentContext, facade);
|
|
||||||
if (handler.handleRequest()) {
|
|
||||||
return Authentication.SEND_SUCCESS;
|
|
||||||
}
|
|
||||||
if (!mandatory)
|
|
||||||
return new DeferredAuthentication(this);
|
|
||||||
AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
|
|
||||||
nodesRegistrationManagement.tryRegister(deployment);
|
|
||||||
|
|
||||||
tokenStore.checkCurrentToken();
|
|
||||||
JettyRequestAuthenticator authenticator = createRequestAuthenticator(request, facade, deployment, tokenStore);
|
|
||||||
AuthOutcome outcome = authenticator.authenticate();
|
|
||||||
if (outcome == AuthOutcome.AUTHENTICATED) {
|
|
||||||
if (facade.isEnded()) {
|
|
||||||
return Authentication.SEND_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Authentication authentication = register(request, authenticator.principal);
|
|
||||||
AuthenticatedActionsHandler authenticatedActionsHandler = new AuthenticatedActionsHandler(deployment, facade);
|
|
||||||
if (authenticatedActionsHandler.handledRequest()) {
|
|
||||||
return Authentication.SEND_SUCCESS;
|
|
||||||
}
|
|
||||||
return authentication;
|
|
||||||
|
|
||||||
}
|
|
||||||
AuthChallenge challenge = authenticator.getChallenge();
|
|
||||||
if (challenge != null) {
|
|
||||||
challenge.challenge(facade);
|
|
||||||
}
|
|
||||||
return Authentication.SEND_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract Request resolveRequest(ServletRequest req);
|
|
||||||
|
|
||||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
|
||||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
|
||||||
return new JettyRequestAuthenticator(facade, deployment, tokenStore, -1, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAuthMethod() {
|
|
||||||
return "KEYCLOAK";
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = createAuthentication(userIdentity, request);
|
|
||||||
request.setAuthentication(authentication);
|
|
||||||
}
|
|
||||||
return authentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Authentication createAuthentication(UserIdentity userIdentity, Request request);
|
|
||||||
|
|
||||||
public static abstract class KeycloakAuthentication extends UserAuthentication {
|
|
||||||
public KeycloakAuthentication(String method, UserIdentity userIdentity) {
|
|
||||||
super(method, userIdentity);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.core;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.KeycloakPrincipal;
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
|
||||||
import org.keycloak.adapters.CookieTokenStore;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle storage of token info in cookie. Per-request object.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class JettyCookieTokenStore implements AdapterTokenStore {
|
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger(JettyCookieTokenStore.class);
|
|
||||||
|
|
||||||
private Request request;
|
|
||||||
private HttpFacade facade;
|
|
||||||
private KeycloakDeployment deployment;
|
|
||||||
|
|
||||||
private KeycloakPrincipal<RefreshableKeycloakSecurityContext> authenticatedPrincipal;
|
|
||||||
|
|
||||||
public JettyCookieTokenStore(Request request, HttpFacade facade, KeycloakDeployment deployment) {
|
|
||||||
this.request = request;
|
|
||||||
this.facade = facade;
|
|
||||||
this.deployment = deployment;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkCurrentToken() {
|
|
||||||
this.authenticatedPrincipal = checkPrincipalFromCookie();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCached(RequestAuthenticator authenticator) {
|
|
||||||
// Assuming authenticatedPrincipal set by previous call of checkCurrentToken() during this request
|
|
||||||
if (authenticatedPrincipal != null) {
|
|
||||||
log.debug("remote logged in already. Establish state from cookie");
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = authenticatedPrincipal.getKeycloakSecurityContext();
|
|
||||||
|
|
||||||
if (!securityContext.getRealm().equals(deployment.getRealm())) {
|
|
||||||
log.debug("Account from cookie is from a different realm than for the request.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
securityContext.setCurrentRequestInfo(deployment, this);
|
|
||||||
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
|
||||||
|
|
||||||
JettyRequestAuthenticator jettyAuthenticator = (JettyRequestAuthenticator) authenticator;
|
|
||||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = AdapterUtils.createPrincipal(deployment, securityContext);
|
|
||||||
jettyAuthenticator.principal = principal;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveAccountInfo(OidcKeycloakAccount account) {
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
|
||||||
CookieTokenStore.setTokenCookie(deployment, facade, securityContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logout() {
|
|
||||||
CookieTokenStore.removeCookie(deployment, facade);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshCallback(RefreshableKeycloakSecurityContext secContext) {
|
|
||||||
CookieTokenStore.setTokenCookie(deployment, facade, secContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify if we already have authenticated and active principal in cookie. Perform refresh if it's not active
|
|
||||||
*
|
|
||||||
* @return valid principal
|
|
||||||
*/
|
|
||||||
protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> checkPrincipalFromCookie() {
|
|
||||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = CookieTokenStore.getPrincipalFromCookie(deployment, facade, this);
|
|
||||||
if (principal == null) {
|
|
||||||
log.debug("Account was not in cookie or was invalid");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshableKeycloakSecurityContext session = principal.getKeycloakSecurityContext();
|
|
||||||
|
|
||||||
if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return principal;
|
|
||||||
boolean success = session.refreshExpiredToken(false);
|
|
||||||
if (success && session.isActive()) return principal;
|
|
||||||
|
|
||||||
log.debugf("Cleanup and expire cookie for user %s after failed refresh", principal.getName());
|
|
||||||
CookieTokenStore.removeCookie(deployment, facade);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveRequest() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean restoreRequest() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.core;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.KeycloakPrincipal;
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class JettyRequestAuthenticator extends RequestAuthenticator {
|
|
||||||
protected static final Logger log = Logger.getLogger(JettyRequestAuthenticator.class);
|
|
||||||
protected Request request;
|
|
||||||
protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
|
|
||||||
|
|
||||||
public JettyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
|
|
||||||
super(facade, deployment, tokenStore, sslRedirectPort);
|
|
||||||
this.request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected OAuthRequestAuthenticator createOAuthAuthenticator() {
|
|
||||||
return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
|
|
||||||
principal = skp;
|
|
||||||
final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
|
|
||||||
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
|
||||||
OidcKeycloakAccount account = new OidcKeycloakAccount() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Principal getPrincipal() {
|
|
||||||
return skp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getRoles() {
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSecurityContext getKeycloakSecurityContext() {
|
|
||||||
return securityContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
|
||||||
this.tokenStore.saveAccountInfo(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
|
|
||||||
this.principal = principal;
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
|
|
||||||
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Completing bearer authentication. Bearer roles: " + roles);
|
|
||||||
}
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String changeHttpSessionId(boolean create) {
|
|
||||||
HttpSession session = request.getSession(create);
|
|
||||||
return session != null ? session.getId() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.core;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.KeycloakPrincipal;
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle storage of token info in HTTP Session. Per-request object
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class JettySessionTokenStore implements AdapterTokenStore {
|
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger(JettySessionTokenStore.class);
|
|
||||||
|
|
||||||
private Request request;
|
|
||||||
protected KeycloakDeployment deployment;
|
|
||||||
protected AdapterSessionStore sessionStore;
|
|
||||||
|
|
||||||
public JettySessionTokenStore(Request request, KeycloakDeployment deployment, AdapterSessionStore sessionStore) {
|
|
||||||
this.request = request;
|
|
||||||
this.deployment = deployment;
|
|
||||||
this.sessionStore = sessionStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkCurrentToken() {
|
|
||||||
if (request.getSession(false) == null) return;
|
|
||||||
RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
if (session == null) return;
|
|
||||||
|
|
||||||
// just in case session got serialized
|
|
||||||
if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
|
|
||||||
|
|
||||||
if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
|
|
||||||
|
|
||||||
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
|
|
||||||
// not be updated
|
|
||||||
boolean success = session.refreshExpiredToken(false);
|
|
||||||
if (success && session.isActive()) return;
|
|
||||||
|
|
||||||
// Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
|
|
||||||
request.getSession().removeAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
request.getSession().invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCached(RequestAuthenticator authenticator) {
|
|
||||||
if (request.getSession(false) == null || request.getSession().getAttribute(KeycloakSecurityContext.class.getName()) == null)
|
|
||||||
return false;
|
|
||||||
log.debug("remote logged in already. Establish state from session");
|
|
||||||
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
if (!deployment.getRealm().equals(securityContext.getRealm())) {
|
|
||||||
log.debug("Account from cookie is from a different realm than for the request.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
securityContext.setCurrentRequestInfo(deployment, this);
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
|
||||||
|
|
||||||
JettyRequestAuthenticator jettyAuthenticator = (JettyRequestAuthenticator) authenticator;
|
|
||||||
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = AdapterUtils.createPrincipal(deployment, securityContext);
|
|
||||||
jettyAuthenticator.principal = principal;
|
|
||||||
restoreRequest();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveAccountInfo(OidcKeycloakAccount account) {
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
|
|
||||||
request.getSession().setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logout() {
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
if (session != null) {
|
|
||||||
session.removeAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveRequest() {
|
|
||||||
sessionStore.saveRequest();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean restoreRequest() {
|
|
||||||
return sessionStore.restoreRequest();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.core;
|
|
||||||
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.OIDCHttpFacade;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class OIDCJettyHttpFacade extends JettyHttpFacade implements OIDCHttpFacade {
|
|
||||||
|
|
||||||
public OIDCJettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
|
|
||||||
super(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSecurityContext getSecurityContext() {
|
|
||||||
return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,150 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<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>999.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-jetty94-adapter</artifactId>
|
|
||||||
<name>Keycloak Jetty 9.4.x Integration</name>
|
|
||||||
<properties>
|
|
||||||
<keycloak.osgi.export>
|
|
||||||
org.keycloak.adapters.jetty.*
|
|
||||||
</keycloak.osgi.export>
|
|
||||||
<keycloak.osgi.import>
|
|
||||||
org.eclipse.jetty.*;resolution:=optional,
|
|
||||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
|
||||||
org.keycloak.*;version="${project.version}",
|
|
||||||
*;resolution:=optional
|
|
||||||
</keycloak.osgi.import>
|
|
||||||
</properties>
|
|
||||||
<description />
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>jboss-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>commons-logging-jboss-logging</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-adapter-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpclient</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk18on</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-annotations</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-server</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-util</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-security</artifactId>
|
|
||||||
<version>${jetty94.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>bundle-manifest</id>
|
|
||||||
<phase>process-classes</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>manifest</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<instructions>
|
|
||||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
|
||||||
<Bundle-Name>${project.name}</Bundle-Name>
|
|
||||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
|
||||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
|
||||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class Jetty94RequestAuthenticator extends JettyRequestAuthenticator {
|
|
||||||
public Jetty94RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
|
|
||||||
super(facade, deployment, tokenStore, sslRedirectPort, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String changeHttpSessionId(boolean create) {
|
|
||||||
Request request = this.request;
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
if (session == null) {
|
|
||||||
return request.getSession(true).getId();
|
|
||||||
}
|
|
||||||
if (!deployment.isTurnOffChangeSessionIdOnLogin()) return request.changeSessionId();
|
|
||||||
else return session.getId();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.session.Session;
|
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class Jetty94SessionManager implements JettySessionManager {
|
|
||||||
protected SessionHandler sessionHandler;
|
|
||||||
|
|
||||||
public Jetty94SessionManager(SessionHandler sessionHandler) {
|
|
||||||
this.sessionHandler = sessionHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpSession getHttpSession(String extendedId) {
|
|
||||||
// inlined code from sessionHandler.getHttpSession(extendedId) since the method visibility changed to protected
|
|
||||||
|
|
||||||
String id = sessionHandler.getSessionIdManager().getId(extendedId);
|
|
||||||
Session session = sessionHandler.getSession(id);
|
|
||||||
|
|
||||||
if (session != null && !session.getExtendedId().equals(extendedId)) {
|
|
||||||
session.setIdChanged(true);
|
|
||||||
}
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
|
||||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
|
||||||
import org.keycloak.common.util.MultivaluedHashMap;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
|
||||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
|
||||||
protected Request myRequest;
|
|
||||||
|
|
||||||
public JettyAdapterSessionStore(Request request) {
|
|
||||||
this.myRequest = request; // for IDE/compilation purposes
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MultiMap<String> extractFormParameters(Request base_request) {
|
|
||||||
MultiMap<String> formParameters = new MultiMap<String>();
|
|
||||||
base_request.extractFormParameters(formParameters);
|
|
||||||
return formParameters;
|
|
||||||
}
|
|
||||||
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
|
|
||||||
base_request.setContentParameters(j_post);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean restoreRequest() {
|
|
||||||
HttpSession session = myRequest.getSession(false);
|
|
||||||
if (session == null) return false;
|
|
||||||
synchronized (session) {
|
|
||||||
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
|
|
||||||
if (j_uri != null) {
|
|
||||||
// check if the request is for the same url as the original and restore
|
|
||||||
// params if it was a post
|
|
||||||
StringBuffer buf = myRequest.getRequestURL();
|
|
||||||
if (myRequest.getQueryString() != null)
|
|
||||||
buf.append("?").append(myRequest.getQueryString());
|
|
||||||
if (j_uri.equals(buf.toString())) {
|
|
||||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
|
||||||
myRequest.setMethod(method);
|
|
||||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
|
||||||
if (j_post != null) {
|
|
||||||
myRequest.setContentType("application/x-www-form-urlencoded");
|
|
||||||
MultiMap<String> map = new MultiMap<String>();
|
|
||||||
for (String key : j_post.keySet()) {
|
|
||||||
for (String val : j_post.getList(key)) {
|
|
||||||
map.add(key, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
restoreFormParameters(map, myRequest);
|
|
||||||
}
|
|
||||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
|
||||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
|
||||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveRequest() {
|
|
||||||
// remember the current URI
|
|
||||||
HttpSession session = myRequest.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) {
|
|
||||||
StringBuffer buf = myRequest.getRequestURL();
|
|
||||||
if (myRequest.getQueryString() != null)
|
|
||||||
buf.append("?").append(myRequest.getQueryString());
|
|
||||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
|
||||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
|
||||||
|
|
||||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
|
||||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
|
||||||
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
|
|
||||||
for (String key : formParameters.keySet()) {
|
|
||||||
for (Object value : formParameters.getValues(key)) {
|
|
||||||
map.add(key, (String) value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
session.setAttribute(CACHED_FORM_PARAMETERS, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty;
|
|
||||||
|
|
||||||
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 org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
|
||||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
|
||||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
|
||||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
|
|
||||||
|
|
||||||
public KeycloakJettyAuthenticator() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Request resolveRequest(ServletRequest req) {
|
|
||||||
return Request.getBaseRequest(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
|
|
||||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
|
||||||
@Override
|
|
||||||
public Authentication logout(ServletRequest servletRequest) {
|
|
||||||
logoutCurrent((Request) servletRequest);
|
|
||||||
return super.logout(servletRequest);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
|
||||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
|
||||||
return new JettyUserSessionManagement(new Jetty94SessionManager(request.getSessionHandler()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
|
||||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
|
||||||
return new Jetty94RequestAuthenticator(facade, deployment, tokenStore, -1, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<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>999.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<name>Keycloak Jetty Integration</name>
|
|
||||||
<description/>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-jetty-integration-pom</artifactId>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>jetty-core</module>
|
|
||||||
<module>jetty9.4</module>
|
|
||||||
</modules>
|
|
||||||
</project>
|
|
|
@ -34,7 +34,6 @@
|
||||||
<module>adapter-core</module>
|
<module>adapter-core</module>
|
||||||
<module>installed</module>
|
<module>installed</module>
|
||||||
<module>jaxrs-oauth-client</module>
|
<module>jaxrs-oauth-client</module>
|
||||||
<module>jetty</module>
|
|
||||||
<module>js</module>
|
<module>js</module>
|
||||||
<module>servlet-filter</module>
|
<module>servlet-filter</module>
|
||||||
<module>jakarta-servlet-filter</module>
|
<module>jakarta-servlet-filter</module>
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<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>999.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
|
||||||
<name>Keycloak Jetty Adapter SPI</name>
|
|
||||||
<properties>
|
|
||||||
<jetty9.version>8.1.17.v20150415</jetty9.version>
|
|
||||||
<keycloak.osgi.export>
|
|
||||||
org.keycloak.adapters.jetty.spi.*
|
|
||||||
</keycloak.osgi.export>
|
|
||||||
<keycloak.osgi.import>
|
|
||||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
|
||||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
|
||||||
org.keycloak.*;version="${project.version}",
|
|
||||||
*;resolution:=optional
|
|
||||||
</keycloak.osgi.import>
|
|
||||||
</properties>
|
|
||||||
<description />
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>jboss-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-common</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-adapter-spi</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-server</artifactId>
|
|
||||||
<version>${jetty9.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-util</artifactId>
|
|
||||||
<version>${jetty9.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-security</artifactId>
|
|
||||||
<version>${jetty9.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>bundle-manifest</id>
|
|
||||||
<phase>process-classes</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>manifest</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<instructions>
|
|
||||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
|
||||||
<Bundle-Name>${project.name}</Bundle-Name>
|
|
||||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
|
||||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
|
||||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,258 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.spi;
|
|
||||||
|
|
||||||
import org.keycloak.adapters.spi.AuthenticationError;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
import org.keycloak.adapters.spi.LogoutError;
|
|
||||||
import org.keycloak.common.util.MultivaluedHashMap;
|
|
||||||
import org.keycloak.common.util.UriUtils;
|
|
||||||
|
|
||||||
import javax.security.cert.X509Certificate;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class JettyHttpFacade implements HttpFacade {
|
|
||||||
public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD";
|
|
||||||
protected org.eclipse.jetty.server.Request request;
|
|
||||||
protected HttpServletResponse response;
|
|
||||||
protected RequestFacade requestFacade = new RequestFacade();
|
|
||||||
protected ResponseFacade responseFacade = new ResponseFacade();
|
|
||||||
protected MultivaluedHashMap<String, String> queryParameters;
|
|
||||||
|
|
||||||
public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
|
|
||||||
this.request = request;
|
|
||||||
this.response = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Request getRequest() {
|
|
||||||
return requestFacade;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response getResponse() {
|
|
||||||
return responseFacade;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public X509Certificate[] getCertificateChain() {
|
|
||||||
throw new IllegalStateException("Not supported yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnded() {
|
|
||||||
return responseFacade.isEnded();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class RequestFacade implements Request {
|
|
||||||
|
|
||||||
private InputStream inputStream;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getURI() {
|
|
||||||
StringBuffer buf = request.getRequestURL();
|
|
||||||
if (request.getQueryString() != null) {
|
|
||||||
buf.append('?').append(request.getQueryString());
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRelativePath() {
|
|
||||||
return request.getServletPath() + (request.getPathInfo() != null ? request.getPathInfo() : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFirstParam(String param) {
|
|
||||||
return request.getParameter(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSecure() {
|
|
||||||
return request.isSecure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getQueryParamValue(String paramName) {
|
|
||||||
if (queryParameters == null) {
|
|
||||||
queryParameters = UriUtils.decodeQueryString(request.getQueryString());
|
|
||||||
}
|
|
||||||
return queryParameters.getFirst(paramName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cookie getCookie(String cookieName) {
|
|
||||||
if (request.getCookies() == null) return null;
|
|
||||||
javax.servlet.http.Cookie cookie = null;
|
|
||||||
for (javax.servlet.http.Cookie c : request.getCookies()) {
|
|
||||||
if (c.getName().equals(cookieName)) {
|
|
||||||
cookie = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cookie == null) return null;
|
|
||||||
return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getHeaders(String name) {
|
|
||||||
Enumeration<String> headers = request.getHeaders(name);
|
|
||||||
if (headers == null) return null;
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
while (headers.hasMoreElements()) {
|
|
||||||
list.add(headers.nextElement());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream() {
|
|
||||||
return getInputStream(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream(boolean buffered) {
|
|
||||||
if (inputStream != null) {
|
|
||||||
return inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffered) {
|
|
||||||
try {
|
|
||||||
return inputStream = new BufferedInputStream(request.getInputStream());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return request.getInputStream();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMethod() {
|
|
||||||
return request.getMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeader(String name) {
|
|
||||||
return request.getHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRemoteAddr() {
|
|
||||||
return request.getRemoteAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setError(AuthenticationError error) {
|
|
||||||
request.setAttribute(AuthenticationError.class.getName(), error);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setError(LogoutError error) {
|
|
||||||
request.setAttribute(LogoutError.class.getName(), error);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class ResponseFacade implements Response {
|
|
||||||
protected boolean ended;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStatus(int status) {
|
|
||||||
response.setStatus(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addHeader(String name, String value) {
|
|
||||||
response.addHeader(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHeader(String name, String value) {
|
|
||||||
response.setHeader(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetCookie(String name, String path) {
|
|
||||||
setCookie(name, "", path, null, 0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
|
|
||||||
javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(name, value);
|
|
||||||
if (domain != null) cookie.setDomain(domain);
|
|
||||||
if (path != null) cookie.setPath(path);
|
|
||||||
if (secure) cookie.setSecure(true);
|
|
||||||
if (httpOnly) cookie.setHttpOnly(httpOnly);
|
|
||||||
cookie.setMaxAge(maxAge);
|
|
||||||
response.addCookie(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OutputStream getOutputStream() {
|
|
||||||
try {
|
|
||||||
return response.getOutputStream();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendError(int code) {
|
|
||||||
try {
|
|
||||||
response.sendError(code);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendError(int code, String message) {
|
|
||||||
try {
|
|
||||||
response.sendError(code, message);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void end() {
|
|
||||||
ended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnded() {
|
|
||||||
return ended;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.spi;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public interface JettySessionManager {
|
|
||||||
|
|
||||||
public HttpSession getHttpSession(String id);
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.spi;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.adapters.spi.UserSessionManagement;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class JettyUserSessionManagement implements UserSessionManagement {
|
|
||||||
private static final org.jboss.logging.Logger log = Logger.getLogger(JettyUserSessionManagement.class);
|
|
||||||
protected JettySessionManager sessionManager;
|
|
||||||
|
|
||||||
public JettyUserSessionManagement(JettySessionManager sessionManager) {
|
|
||||||
this.sessionManager = sessionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logoutAll() {
|
|
||||||
// todo not implemented yet
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void logoutHttpSessions(List<String> ids) {
|
|
||||||
log.trace("---> logoutHttpSessions");
|
|
||||||
for (String id : ids) {
|
|
||||||
HttpSession httpSession = sessionManager.getHttpSession(id);
|
|
||||||
if (httpSession != null) httpSession.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.adapters.jetty.spi;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Handler;
|
|
||||||
import org.eclipse.jetty.server.SessionManager;
|
|
||||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class WrappingSessionHandler extends SessionHandler {
|
|
||||||
|
|
||||||
public WrappingSessionHandler() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public WrappingSessionHandler(SessionManager mgr) {
|
|
||||||
super(mgr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHandler(Handler handler) {
|
|
||||||
if (getHandler() != null && getHandler() instanceof HandlerWrapper) {
|
|
||||||
HandlerWrapper wrappedHandler = (HandlerWrapper) getHandler();
|
|
||||||
wrappedHandler.setHandler(handler);
|
|
||||||
} else {
|
|
||||||
super.setHandler(handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,6 +36,5 @@
|
||||||
<module>servlet-adapter-spi</module>
|
<module>servlet-adapter-spi</module>
|
||||||
<module>jakarta-servlet-adapter-spi</module>
|
<module>jakarta-servlet-adapter-spi</module>
|
||||||
<module>jboss-adapter-core</module>
|
<module>jboss-adapter-core</module>
|
||||||
<module>jetty-adapter-spi</module>
|
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
15
pom.xml
15
pom.xml
|
@ -1059,21 +1059,6 @@
|
||||||
<artifactId>keycloak-jboss-adapter-core</artifactId>
|
<artifactId>keycloak-jboss-adapter-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty-core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty94-adapter</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-as7-subsystem</artifactId>
|
<artifactId>keycloak-as7-subsystem</artifactId>
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
<artifactId>integration-arquillian-servers-app-server-jetty-common</artifactId>
|
<artifactId>integration-arquillian-servers-app-server-jetty-common</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty94-adapter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.arquillian.container</groupId>
|
<groupId>org.jboss.arquillian.container</groupId>
|
||||||
<artifactId>arquillian-jetty-embedded-9</artifactId>
|
<artifactId>arquillian-jetty-embedded-9</artifactId>
|
||||||
|
|
|
@ -29,11 +29,6 @@
|
||||||
|
|
||||||
<artifactId>integration-arquillian-servers-app-server-jetty-common</artifactId>
|
<artifactId>integration-arquillian-servers-app-server-jetty-common</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty94-adapter</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
|
<artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
<feature>camel-jetty9</feature>
|
<feature>camel-jetty9</feature>
|
||||||
<feature>cxf</feature>
|
<feature>cxf</feature>
|
||||||
<feature>keycloak</feature>
|
<feature>keycloak</feature>
|
||||||
<feature>keycloak-jetty9-adapter</feature>
|
|
||||||
<bundle dependency="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.12.1</bundle>
|
<bundle dependency="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.12.1</bundle>
|
||||||
<bundle dependency="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.12.1</bundle>
|
<bundle dependency="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.12.1</bundle>
|
||||||
<bundle>mvn:org.keycloak.testsuite/fuse-example-product-portal/${project.version}</bundle>
|
<bundle>mvn:org.keycloak.testsuite/fuse-example-product-portal/${project.version}</bundle>
|
||||||
|
|
Loading…
Reference in a new issue