diff --git a/adapters/spi/pom.xml b/adapters/spi/pom.xml index 64b28a099a..cdfe1b127f 100755 --- a/adapters/spi/pom.xml +++ b/adapters/spi/pom.xml @@ -32,7 +32,6 @@ adapter-spi - undertow-adapter-spi jboss-adapter-core diff --git a/adapters/spi/undertow-adapter-spi/pom.xml b/adapters/spi/undertow-adapter-spi/pom.xml deleted file mode 100755 index 15c552398f..0000000000 --- a/adapters/spi/undertow-adapter-spi/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - keycloak-parent - org.keycloak - 999.0.0-SNAPSHOT - ../../../pom.xml - - 4.0.0 - - keycloak-undertow-adapter-spi - Keycloak Undertow Integration SPI - - - - - 11 - - - - - org.jboss.logging - jboss-logging - provided - - - org.keycloak - keycloak-adapter-spi - - - org.keycloak - keycloak-common - - - org.jboss.spec.javax.servlet - jboss-servlet-api_3.0_spec - provided - - - io.undertow - undertow-servlet - provided - - - io.undertow - undertow-core - provided - - - junit - junit - test - - - diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ChangeSessionId.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ChangeSessionId.java deleted file mode 100755 index 24eef7e0dd..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ChangeSessionId.java +++ /dev/null @@ -1,68 +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.undertow; - -import io.undertow.server.HttpServerExchange; -import io.undertow.server.session.Session; -import io.undertow.servlet.api.DeploymentInfo; -import io.undertow.servlet.handlers.ServletRequestContext; -import io.undertow.servlet.spec.HttpSessionImpl; -import io.undertow.servlet.spec.ServletContextImpl; - -import java.lang.reflect.Method; -import java.security.AccessController; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ChangeSessionId { - /** - * This is a hack to be backward compatible between Undertow 1.3+ and versions lower. In Undertow 1.3, a new - * switch was added setChangeSessionIdOnLogin, this screws up session management for keycloak as after the session id - * is uploaded to Keycloak, undertow changes the session id and it can't be invalidated. - * - * @param deploymentInfo - */ - public static void turnOffChangeSessionIdOnLogin(DeploymentInfo deploymentInfo) { - try { - Method method = DeploymentInfo.class.getMethod("setChangeSessionIdOnLogin", boolean.class); - method.invoke(deploymentInfo, false); - } catch (Exception ignore) { - - } - } - - public static String changeSessionId(HttpServerExchange exchange, boolean create) { - final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); - ServletContextImpl currentServletContext = sc.getCurrentServletContext(); - HttpSessionImpl session = currentServletContext.getSession(exchange, create); - if (session == null) { - return null; - } - Session underlyingSession; - if(System.getSecurityManager() == null) { - underlyingSession = session.getSession(); - } else { - underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session)); - } - - - return underlyingSession.changeSessionId(exchange, currentServletContext.getSessionConfig()); - } -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java deleted file mode 100755 index 0d4aae7161..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java +++ /dev/null @@ -1,82 +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.undertow; - -import io.undertow.server.HttpServerExchange; -import io.undertow.server.session.Session; -import io.undertow.servlet.handlers.ServletRequestContext; -import io.undertow.servlet.spec.HttpSessionImpl; - -import javax.servlet.http.HttpSession; -import java.io.Serializable; -import java.security.AccessController; - -/** - * Saved servlet request. - * - * Note bill burke: I had to fork this because Undertow was automatically restoring the request before the code could be - * processed and redirected. - * - * CachedAuthenticatedSessionHandler was restoring the request before the authentication manager could read the code from the URI - * Originally, I copied SavedRequest as is, but there are type mismatches between Undertow 1.1.1 and 1.3.10. - * So, trySaveRequest calls the same undertow version, removes the saved request, stores it in a different session attribute, - * then restores the old attribute later - * - * - * @author Stuart Douglas - */ -public class SavedRequest implements Serializable { - - private static final String SESSION_KEY = SavedRequest.class.getName(); - - public static void trySaveRequest(final HttpServerExchange exchange) { - io.undertow.servlet.util.SavedRequest.trySaveRequest(exchange); - final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); - HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true); - Session underlyingSession; - if(System.getSecurityManager() == null) { - underlyingSession = session.getSession(); - } else { - underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session)); - } - io.undertow.servlet.util.SavedRequest request = (io.undertow.servlet.util.SavedRequest) underlyingSession.removeAttribute(io.undertow.servlet.util.SavedRequest.class.getName()); - if (request != null) underlyingSession.setAttribute(SESSION_KEY, request); - - - } - - public static void tryRestoreRequest(final HttpServerExchange exchange, HttpSession session) { - if(session instanceof HttpSessionImpl) { - - Session underlyingSession; - if(System.getSecurityManager() == null) { - underlyingSession = ((HttpSessionImpl) session).getSession(); - } else { - underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session)); - } - io.undertow.servlet.util.SavedRequest request = (io.undertow.servlet.util.SavedRequest) underlyingSession.removeAttribute(SESSION_KEY); - if (request != null) { - underlyingSession.setAttribute(io.undertow.servlet.util.SavedRequest.class.getName(), request); - io.undertow.servlet.util.SavedRequest.tryRestoreRequest(exchange, session); - - } - - } - } - -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ServletHttpFacade.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ServletHttpFacade.java deleted file mode 100755 index fbcd6d3219..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/ServletHttpFacade.java +++ /dev/null @@ -1,96 +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.undertow; - -import io.undertow.server.HttpServerExchange; -import io.undertow.servlet.handlers.ServletRequestContext; -import org.keycloak.adapters.spi.AuthenticationError; -import org.keycloak.adapters.spi.LogoutError; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ServletHttpFacade extends UndertowHttpFacade { - protected HttpServletRequest request; - protected HttpServletResponse response; - - public ServletHttpFacade(HttpServerExchange exchange) { - super(exchange); - final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); - request = (HttpServletRequest)servletRequestContext.getServletRequest(); - response = (HttpServletResponse)servletRequestContext.getServletResponse(); - } - - protected class RequestFacade extends UndertowHttpFacade.RequestFacade { - @Override - public String getFirstParam(String param) { - return request.getParameter(param); - } - - @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 extends UndertowHttpFacade.ResponseFacade { - // can't call sendError from a challenge. Undertow ends up calling send error. - /* - @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 Response getResponse() { - return new ResponseFacade(); - } - - @Override - public Request getRequest() { - return new RequestFacade(); - } -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java deleted file mode 100755 index fcde53737b..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java +++ /dev/null @@ -1,48 +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.undertow; - -import io.undertow.server.session.SessionManager; -import org.keycloak.adapters.spi.UserSessionManagement; - -import java.util.List; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class SessionManagementBridge implements UserSessionManagement { - - protected UndertowUserSessionManagement userSessionManagement; - protected SessionManager sessionManager; - - public SessionManagementBridge(UndertowUserSessionManagement userSessionManagement, SessionManager sessionManager) { - this.userSessionManagement = userSessionManagement; - this.sessionManager = sessionManager; - } - - @Override - public void logoutAll() { - userSessionManagement.logoutAll(sessionManager); - } - - @Override - public void logoutHttpSessions(List ids) { - userSessionManagement.logoutHttpSessions(sessionManager, ids); - } - -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java deleted file mode 100755 index c86a54f0a4..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java +++ /dev/null @@ -1,298 +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.undertow; - -import io.undertow.server.HttpServerExchange; -import io.undertow.server.handlers.CookieImpl; -import io.undertow.server.handlers.form.FormData; -import io.undertow.server.handlers.form.FormData.FormValue; -import io.undertow.server.handlers.form.FormDataParser; -import io.undertow.server.handlers.form.FormParserFactory; -import io.undertow.servlet.handlers.ServletRequestContext; -import io.undertow.util.AttachmentKey; -import io.undertow.util.Headers; -import io.undertow.util.HttpString; -import org.keycloak.adapters.spi.AuthenticationError; -import org.keycloak.adapters.spi.HttpFacade; -import org.keycloak.adapters.spi.LogoutError; -import org.keycloak.common.util.KeycloakUriBuilder; - -import javax.security.cert.X509Certificate; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Deque; -import java.util.List; -import java.util.Map; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class UndertowHttpFacade implements HttpFacade { - public static final AttachmentKey AUTH_ERROR_ATTACHMENT_KEY = AttachmentKey.create(AuthenticationError.class); - public static final AttachmentKey LOGOUT_ERROR_ATTACHMENT_KEY = AttachmentKey.create(LogoutError.class); - - protected HttpServerExchange exchange; - protected RequestFacade requestFacade = new RequestFacade(); - protected ResponseFacade responseFacade = new ResponseFacade(); - - public UndertowHttpFacade(HttpServerExchange exchange) { - this.exchange = exchange; - } - - @Override - public Request getRequest() { - return requestFacade; - } - - @Override - public Response getResponse() { - return responseFacade; - } - - @Override - public X509Certificate[] getCertificateChain() { - X509Certificate[] chain = new X509Certificate[0]; - try { - chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain(); - } catch (Exception ignore) { - - } - return chain; - } - - protected class RequestFacade implements Request { - - private InputStream inputStream; - private final FormParserFactory formParserFactory = FormParserFactory.builder().build(); - private FormData formData; - - @Override - public String getURI() { - KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(exchange.getRequestURI()) - .replaceQuery(exchange.getQueryString()); - if (!exchange.isHostIncludedInRequestURI()) uriBuilder.scheme(exchange.getRequestScheme()).host(exchange.getHostAndPort()); - return uriBuilder.buildAsString(); - } - - @Override - public String getRelativePath() { - return exchange.getRelativePath(); - } - - @Override - public boolean isSecure() { - String protocol = exchange.getRequestScheme(); - return protocol.equalsIgnoreCase("https"); - } - - @Override - public String getFirstParam(String param) { - Deque values = exchange.getQueryParameters().get(param); - - if (values != null && !values.isEmpty()) { - return values.getFirst(); - } - - if (formData == null && "post".equalsIgnoreCase(getMethod())) { - FormDataParser parser = formParserFactory.createParser(exchange); - try { - formData = parser.parseBlocking(); - } catch (IOException cause) { - throw new RuntimeException("Failed to parse form parameters", cause); - } - } - - if (formData != null) { - Deque formValues = formData.get(param); - - if (formValues != null && !formValues.isEmpty()) { - FormValue firstValue = formValues.getFirst(); - - if (!firstValue.isFile()) { - return firstValue.getValue(); - } - } - } - - return null; - } - - @Override - public String getQueryParamValue(String param) { - Map> queryParameters = exchange.getQueryParameters(); - if (queryParameters == null) return null; - Deque strings = queryParameters.get(param); - if (strings == null) return null; - return strings.getFirst(); - } - - @Override - public Cookie getCookie(String cookieName) { - Map requestCookies = exchange.getRequestCookies(); - if (requestCookies == null) return null; - io.undertow.server.handlers.Cookie cookie = requestCookies.get(cookieName); - if (cookie == null) return null; - return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath()); - } - - @Override - public List getHeaders(String name) { - return exchange.getRequestHeaders().get(name); - } - - @Override - public String getMethod() { - return exchange.getRequestMethod().toString(); - } - - - - @Override - public String getHeader(String name) { - return exchange.getRequestHeaders().getFirst(name); - } - - @Override - public InputStream getInputStream() { - return getInputStream(false); - } - - @Override - public InputStream getInputStream(boolean buffered) { - if (!exchange.isBlocking()) exchange.startBlocking(); - - if (inputStream != null) { - return inputStream; - } - - if (buffered) { - ServletRequestContext context = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); - ServletRequest servletRequest = context.getServletRequest(); - - inputStream = new BufferedInputStream(exchange.getInputStream()); - - context.setServletRequest(UndertowHttpServletRequest.setupServletInputStream(servletRequest, inputStream)); - return inputStream; - } - - return exchange.getInputStream(); - } - - @Override - public String getRemoteAddr() { - InetSocketAddress sourceAddress = exchange.getSourceAddress(); - if (sourceAddress == null) { - return ""; - } - InetAddress address = sourceAddress.getAddress(); - if (address == null) { - // this is unresolved, so we just return the host name not exactly spec, but if the name should be - // resolved then a PeerNameResolvingHandler should be used and this is probably better than just - // returning null - return sourceAddress.getHostString(); - } - return address.getHostAddress(); - } - - @Override - public void setError(AuthenticationError error) { - exchange.putAttachment(AUTH_ERROR_ATTACHMENT_KEY, error); - } - - @Override - public void setError(LogoutError error) { - exchange.putAttachment(LOGOUT_ERROR_ATTACHMENT_KEY, error); - - } - } - - protected class ResponseFacade implements Response { - @Override - public void setStatus(int status) { - exchange.setResponseCode(status); - } - - @Override - public void addHeader(String name, String value) { - exchange.getResponseHeaders().add(new HttpString(name), value); - } - - @Override - public void setHeader(String name, String value) { - exchange.getResponseHeaders().put(new HttpString(name), value); - } - - @Override - public void resetCookie(String name, String path) { - CookieImpl cookie = new CookieImpl(name, ""); - cookie.setMaxAge(0); - cookie.setPath(path); - exchange.setResponseCookie(cookie); - } - - @Override - public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) { - CookieImpl cookie = new CookieImpl(name, value); - cookie.setPath(path); - cookie.setDomain(domain); - cookie.setMaxAge(maxAge); - cookie.setSecure(secure); - cookie.setHttpOnly(httpOnly); - exchange.setResponseCookie(cookie); - } - - @Override - public OutputStream getOutputStream() { - if (!exchange.isBlocking()) exchange.startBlocking(); - return exchange.getOutputStream(); - } - - @Override - public void sendError(int code) { - exchange.setResponseCode(code); - } - - @Override - public void sendError(int code, String message) { - exchange.setResponseCode(code); - exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/html"); - try { - exchange.getOutputStream().write(message.getBytes()); - } catch (IOException e) { - throw new RuntimeException(e); - } - exchange.endExchange(); - } - - - @Override - public void end() { - exchange.endExchange(); - } - } -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpServletRequest.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpServletRequest.java deleted file mode 100644 index 338f66e22a..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpServletRequest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023 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.undertow; - -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.IOException; -import java.io.InputStream; - -public class UndertowHttpServletRequest { - - public static HttpServletRequestWrapper setupServletInputStream(ServletRequest servletRequest, final InputStream inputStream) { - return new HttpServletRequestWrapper((HttpServletRequest) servletRequest) { - @Override - public ServletInputStream getInputStream() { - inputStream.mark(0); - return new ServletInputStream() { - @Override - public int read() throws IOException { - return inputStream.read(); - } - }; - } - }; - } -} diff --git a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java b/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java deleted file mode 100755 index 953080c214..0000000000 --- a/adapters/spi/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java +++ /dev/null @@ -1,160 +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.undertow; - -import io.undertow.server.HttpServerExchange; -import io.undertow.server.session.Session; -import io.undertow.server.session.SessionConfig; -import io.undertow.server.session.SessionListener; -import io.undertow.server.session.SessionManager; -import org.jboss.logging.Logger; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Manages relationship to users and sessions so that forced admin logout can be implemented - * - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class UndertowUserSessionManagement implements SessionListener { - private static final Logger log = Logger.getLogger(UndertowUserSessionManagement.class); - protected volatile boolean registered; - private final ExecutorService executor = Executors.newSingleThreadExecutor(); - - public void login(SessionManager manager) { - if (!registered) { - manager.registerSessionListener(this); - registered = true; - } - } - - /** - * This method runs the given runnable in the current thread if the session manager does not use distributed sessions, - * or in a separate thread if it does. This is to work around: - *
-     *   org.infinispan.util.concurrent.TimeoutException: ISPN000299: Unable to acquire lock after 15 seconds for key SessionCreationMetaDataKey
-     * 
- * See https://issues.jboss.org/browse/KEYCLOAK-9822 - * @param r - */ - private void workaroundIspnDeadlock(final SessionManager manager, Runnable r) { - if (manager.getClass().getName().equals("org.wildfly.clustering.web.undertow.session.DistributableSessionManager")) { - executor.submit(r); - } else { - r.run(); - } - } - - public void logoutAll(final SessionManager manager) { - final Set allSessions = manager.getAllSessions(); - workaroundIspnDeadlock(manager, new Runnable() { - @Override - public void run() { - for (String sessionId : allSessions) logoutSession(manager, sessionId); - } - }); - } - - public void logoutHttpSessions(final SessionManager manager, final List sessionIds) { - log.debugf("logoutHttpSessions: %s", sessionIds); - - workaroundIspnDeadlock(manager, new Runnable() { - @Override - public void run() { - for (String sessionId : sessionIds) { - logoutSession(manager, sessionId); - } - } - }); - } - - protected void logoutSession(SessionManager manager, String httpSessionId) { - log.debugf("logoutHttpSession: %s", httpSessionId); - Session session = getSessionById(manager, httpSessionId); - try { - if (session != null) session.invalidate(null); - } catch (Exception e) { - log.warnf("Session %s not present or already invalidated.", httpSessionId); - } - } - - protected Session getSessionById(SessionManager manager, final String sessionId) { - // TODO: Workaround for WFLY-3345. Remove this once we move to wildfly 8.2 - if (manager.getClass().getName().equals("org.wildfly.clustering.web.undertow.session.DistributableSessionManager")) { - return manager.getSession(null, new SessionConfig() { - - @Override - public void setSessionId(HttpServerExchange exchange, String sessionId) { - } - - @Override - public void clearSession(HttpServerExchange exchange, String sessionId) { - } - - @Override - public String findSessionId(HttpServerExchange exchange) { - return sessionId; - } - - @Override - public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) { - return null; - } - - @Override - public String rewriteUrl(String originalUrl, String sessionId) { - return null; - } - - }); - - } else { - return manager.getSession(sessionId); - } - } - - - @Override - public void sessionCreated(Session session, HttpServerExchange exchange) { - } - - @Override - public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) { - } - - - @Override - public void sessionIdChanged(Session session, String oldSessionId) { - } - - @Override - public void attributeAdded(Session session, String name, Object value) { - } - - @Override - public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) { - } - - @Override - public void attributeRemoved(Session session, String name, Object oldValue) { - } - -} diff --git a/pom.xml b/pom.xml index 07e71499d6..431e10345b 100644 --- a/pom.xml +++ b/pom.xml @@ -997,11 +997,6 @@ keycloak-saml-as7-subsystem ${project.version} - - org.keycloak - keycloak-undertow-adapter-spi - ${project.version} - org.keycloak keycloak-saml-wildfly-elytron-adapter