From 9b33321cc251e633232ae1d10d4eee49b3d39d19 Mon Sep 17 00:00:00 2001 From: LELEU Jerome Date: Fri, 14 Mar 2014 10:52:42 +0100 Subject: [PATCH] CASC-220: Support front channel SLO logout specific front logout parameter + Tomcat valves update --- .../client/session/SingleSignOutFilter.java | 47 +++++-------- .../client/session/SingleSignOutHandler.java | 68 +++++++++++++++++-- .../session/LogoutMessageGenerator.java | 6 +- .../session/SingleSignOutFilterTests.java | 15 ++-- .../session/SingleSignOutHandlerTests.java | 51 ++++++++++---- .../client/tomcat/v6/SingleSignOutValve.java | 23 ++++++- .../client/tomcat/v7/SingleSignOutValve.java | 23 ++++++- 7 files changed, 168 insertions(+), 65 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java index 1126218..92235dc 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java @@ -23,7 +23,6 @@ import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; import org.jasig.cas.client.util.AbstractConfigurationFilter; import org.jasig.cas.client.util.CommonUtils; @@ -38,25 +37,21 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { private static final SingleSignOutHandler handler = new SingleSignOutHandler(); - /** The prefix url of the CAS server */ - private String casServerUrlPrefix; - - /** Parameter name that stores the state of the CAS server webflow for the callback */ - private String relayStateParameterName = SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME; - public void init(final FilterConfig filterConfig) throws ServletException { if (!isIgnoreInitConfiguration()) { handler.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME)); handler.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName", SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME)); - setRelayStateParameterName(getPropertyFromInitParams(filterConfig, "relayStateParameterName", + handler.setFrontLogoutParameterName(getPropertyFromInitParams(filterConfig, "frontLogoutParameterName", + SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME)); + handler.setRelayStateParameterName(getPropertyFromInitParams(filterConfig, "relayStateParameterName", SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME)); + handler.setCasServerUrlPrefix(getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null)); handler.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig, "artifactParameterOverPost", "false"))); handler.setEagerlyCreateSessions(parseBoolean(getPropertyFromInitParams(filterConfig, "eagerlyCreateSessions", "true"))); - setCasServerUrlPrefix(getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null)); } handler.init(); } @@ -69,20 +64,22 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { handler.setLogoutParameterName(name); } + public void setFrontLogoutParameterName(final String name) { + handler.setFrontLogoutParameterName(name); + } + public void setRelayStateParameterName(final String name) { - this.relayStateParameterName = name; handler.setRelayStateParameterName(name); } + public void setCasServerUrlPrefix(final String casServerUrlPrefix) { + handler.setCasServerUrlPrefix(casServerUrlPrefix); + } + public void setSessionMappingStorage(final SessionMappingStorage storage) { handler.setSessionMappingStorage(storage); } - public void setCasServerUrlPrefix(final String casServerUrlPrefix) { - CommonUtils.assertNotNull(casServerUrlPrefix, "casServerUrlPrefix cannot be null."); - this.casServerUrlPrefix = casServerUrlPrefix; - } - public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; @@ -96,22 +93,10 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { return; } else if (handler.isFrontChannelLogoutRequest(request)) { handler.destroySession(request); - // relay state value - final String relayStateValue = CommonUtils.safeGetParameter(request, this.relayStateParameterName); - // if we have a state value -> redirect to the CAS server to continue the logout process - if (StringUtils.isNotBlank(relayStateValue)) { - final StringBuffer buffer = new StringBuffer(); - buffer.append(casServerUrlPrefix); - if (!this.casServerUrlPrefix.endsWith("/")) { - buffer.append("/"); - } - buffer.append("logout?_eventId=next&"); - buffer.append(this.relayStateParameterName); - buffer.append("="); - buffer.append(CommonUtils.urlEncode(relayStateValue)); - final String redirectUrl = buffer.toString(); - logger.debug("Redirecting back to the CAS server: {}", redirectUrl); - CommonUtils.sendRedirect(response, redirectUrl); + // redirection url to the CAS server + final String redirectionUrl = handler.computeRedirectionToServer(request); + if (redirectionUrl != null) { + CommonUtils.sendRedirect(response, redirectionUrl); } return; } else { diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java index 873d322..1b40afd 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang.StringUtils; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; import org.slf4j.Logger; @@ -46,6 +47,7 @@ public final class SingleSignOutHandler { public final static String DEFAULT_ARTIFACT_PARAMETER_NAME = "ticket"; public final static String DEFAULT_LOGOUT_PARAMETER_NAME = "logoutRequest"; + public final static String DEFAULT_FRONT_LOGOUT_PARAMETER_NAME = "SAMLRequest"; public final static String DEFAULT_RELAY_STATE_PARAMETER_NAME = "RelayState"; /** Logger instance */ @@ -57,12 +59,18 @@ public final class SingleSignOutHandler { /** The name of the artifact parameter. This is used to capture the session identifier. */ private String artifactParameterName = DEFAULT_ARTIFACT_PARAMETER_NAME; - /** Parameter name that stores logout request */ + /** Parameter name that stores logout request for back channel SLO */ private String logoutParameterName = DEFAULT_LOGOUT_PARAMETER_NAME; + /** Parameter name that stores logout request for front channel SLO */ + private String frontLogoutParameterName = DEFAULT_FRONT_LOGOUT_PARAMETER_NAME; + /** Parameter name that stores the state of the CAS server webflow for the callback */ private String relayStateParameterName = DEFAULT_RELAY_STATE_PARAMETER_NAME; + /** The prefix url of the CAS server */ + private String casServerUrlPrefix; + private boolean artifactParameterOverPost = false; private boolean eagerlyCreateSessions = true; @@ -89,12 +97,26 @@ public final class SingleSignOutHandler { } /** - * @param name Name of parameter containing CAS logout request message. + * @param name Name of parameter containing CAS logout request message for back channel SLO. */ public void setLogoutParameterName(final String name) { this.logoutParameterName = name; } + /** + * @param casServerUrlPrefix The prefix url of the CAS server. + */ + public void setCasServerUrlPrefix(final String casServerUrlPrefix) { + this.casServerUrlPrefix = casServerUrlPrefix; + } + + /** + * @param name Name of parameter containing CAS logout request message for front channel SLO. + */ + public void setFrontLogoutParameterName(final String name) { + this.frontLogoutParameterName = name; + } + /** * @param name Name of parameter containing the state of the CAS server webflow. */ @@ -112,8 +134,10 @@ public final class SingleSignOutHandler { public void init() { CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null."); CommonUtils.assertNotNull(this.logoutParameterName, "logoutParameterName cannot be null."); + CommonUtils.assertNotNull(this.frontLogoutParameterName, "frontLogoutParameterName cannot be null."); CommonUtils.assertNotNull(this.sessionMappingStorage, "sessionMappingStorage cannot be null."); CommonUtils.assertNotNull(this.relayStateParameterName, "relayStateParameterName cannot be null."); + CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null."); if (this.artifactParameterOverPost) { this.safeParameters = Arrays.asList(this.logoutParameterName, this.artifactParameterName); @@ -157,7 +181,7 @@ public final class SingleSignOutHandler { */ public boolean isFrontChannelLogoutRequest(final HttpServletRequest request) { return "GET".equals(request.getMethod()) - && CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName)); + && CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.frontLogoutParameterName)); } /** @@ -220,11 +244,13 @@ public final class SingleSignOutHandler { * @param request HTTP request containing a CAS logout message. */ public void destroySession(final HttpServletRequest request) { - String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, - this.safeParameters); - // front channel request -> the message needs to be base64 decoded + decompressed + String logoutMessage; + // front channel logout -> the message needs to be base64 decoded + decompressed if ("GET".equals(request.getMethod())) { - logoutMessage = uncompressLogoutMessage(logoutMessage); + logoutMessage = uncompressLogoutMessage(CommonUtils.safeGetParameter(request, + this.frontLogoutParameterName)); + } else { + logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters); } logger.trace("Logout request:\n{}", logoutMessage); @@ -251,6 +277,34 @@ public final class SingleSignOutHandler { } } + /** + * Compute the redirection url to the CAS server when it's a front channel SLO + * (depending on the relay state parameter). + * + * @param request The HTTP request. + * @return the redirection url to the CAS server. + */ + public String computeRedirectionToServer(final HttpServletRequest request) { + // relay state value + final String relayStateValue = CommonUtils.safeGetParameter(request, this.relayStateParameterName); + // if we have a state value -> redirect to the CAS server to continue the logout process + if (StringUtils.isNotBlank(relayStateValue)) { + final StringBuffer buffer = new StringBuffer(); + buffer.append(casServerUrlPrefix); + if (!this.casServerUrlPrefix.endsWith("/")) { + buffer.append("/"); + } + buffer.append("logout?_eventId=next&"); + buffer.append(this.relayStateParameterName); + buffer.append("="); + buffer.append(CommonUtils.urlEncode(relayStateValue)); + final String redirectUrl = buffer.toString(); + logger.debug("Redirection url to the CAS server: {}", redirectUrl); + return redirectUrl; + } + return null; + } + private boolean isMultipartRequest(final HttpServletRequest request) { return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart"); } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/session/LogoutMessageGenerator.java b/cas-client-core/src/test/java/org/jasig/cas/client/session/LogoutMessageGenerator.java index e30254d..b43ea65 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/session/LogoutMessageGenerator.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/session/LogoutMessageGenerator.java @@ -19,12 +19,12 @@ public final class LogoutMessageGenerator { + "IssueInstant=\"\">@NOT_USED@" + "%s"; - public static String generateLogoutMessage(String sessionIndex) { + public static String generateBackChannelLogoutMessage(String sessionIndex) { return String.format(LOGOUT_REQUEST_TEMPLATE, sessionIndex); } - public static String generateCompressedLogoutMessage(String sessionIndex) { - final String logoutMessage = generateLogoutMessage(sessionIndex); + public static String generateFrontChannelLogoutMessage(String sessionIndex) { + final String logoutMessage = generateBackChannelLogoutMessage(sessionIndex); final Deflater deflater = new Deflater(); deflater.setInput(logoutMessage.getBytes(Charset.forName("ASCII"))); deflater.finish(); diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutFilterTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutFilterTests.java index 82ecd52..64114f9 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutFilterTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutFilterTests.java @@ -79,7 +79,8 @@ public class SingleSignOutFilterTests { @Test public void backChannelRequest() throws IOException, ServletException { - request.setParameter(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME, LogoutMessageGenerator.generateLogoutMessage(TICKET)); + request.setParameter(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME, + LogoutMessageGenerator.generateBackChannelLogoutMessage(TICKET)); request.setMethod("POST"); final MockHttpSession session = new MockHttpSession(); SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().addSessionById(TICKET, session); @@ -89,9 +90,9 @@ public class SingleSignOutFilterTests { @Test public void frontChannelRequest() throws IOException, ServletException { - final String logoutMessage = LogoutMessageGenerator.generateCompressedLogoutMessage(TICKET); - request.setParameter(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME, logoutMessage); - request.setQueryString(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage); + final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET); + request.setParameter(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME, logoutMessage); + request.setQueryString(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage); request.setMethod("GET"); final MockHttpSession session = new MockHttpSession(); SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().addSessionById(TICKET, session); @@ -102,10 +103,10 @@ public class SingleSignOutFilterTests { @Test public void frontChannelRequestRelayState() throws IOException, ServletException { - final String logoutMessage = LogoutMessageGenerator.generateCompressedLogoutMessage(TICKET); - request.setParameter(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME, logoutMessage); + final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET); + request.setParameter(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME, logoutMessage); request.setParameter(SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME, RELAY_STATE); - request.setQueryString(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage + "&" + + request.setQueryString(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage + "&" + SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME + "=" + RELAY_STATE); request.setMethod("GET"); final MockHttpSession session = new MockHttpSession(); diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutHandlerTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutHandlerTests.java index 1479536..c7670e5 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutHandlerTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/session/SingleSignOutHandlerTests.java @@ -37,15 +37,23 @@ public final class SingleSignOutHandlerTests { private final static String ANOTHER_PARAMETER = "anotherParameter"; private final static String TICKET = "ST-xxxxxxxx"; + private final static String URL = "http://mycasserver"; private SingleSignOutHandler handler; private MockHttpServletRequest request; - private final static String logoutParameterName = "logoutRequest"; + private final static String logoutParameterName = "logoutRequest2"; + private final static String frontLogoutParameterName = "SAMLRequest2"; + private final static String relayStateParameterName = "RelayState2"; + private final static String artifactParameterName = "ticket2"; @Before public void setUp() throws Exception { handler = new SingleSignOutHandler(); handler.setLogoutParameterName(logoutParameterName); + handler.setFrontLogoutParameterName(frontLogoutParameterName); + handler.setRelayStateParameterName(relayStateParameterName); + handler.setArtifactParameterName(artifactParameterName); + handler.setCasServerUrlPrefix(URL); handler.init(); request = new MockHttpServletRequest(); } @@ -74,9 +82,9 @@ public final class SingleSignOutHandlerTests { @Test public void isFrontChannelLogoutRequest() { - request.setParameter(logoutParameterName, TICKET); + request.setParameter(frontLogoutParameterName, TICKET); request.setMethod("GET"); - request.setQueryString(logoutParameterName + "=" + TICKET); + request.setQueryString(frontLogoutParameterName + "=" + TICKET); assertTrue(handler.isFrontChannelLogoutRequest(request)); } @@ -94,8 +102,8 @@ public final class SingleSignOutHandlerTests { public void recordSessionKOIfNoSession() { handler.setEagerlyCreateSessions(false); request.setSession(null); - request.setParameter(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME, TICKET); - request.setQueryString(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME + "=" + TICKET); + request.setParameter(artifactParameterName, TICKET); + request.setQueryString(artifactParameterName + "=" + TICKET); handler.recordSession(request); final SessionMappingStorage storage = handler.getSessionMappingStorage(); assertNull(storage.removeSessionByMappingId(TICKET)); @@ -105,8 +113,8 @@ public final class SingleSignOutHandlerTests { public void recordSessionOK() { final MockHttpSession session = new MockHttpSession(); request.setSession(session); - request.setParameter(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME, TICKET); - request.setQueryString(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME + "=" + TICKET); + request.setParameter(artifactParameterName, TICKET); + request.setQueryString(artifactParameterName + "=" + TICKET); handler.recordSession(request); final SessionMappingStorage storage = handler.getSessionMappingStorage(); assertEquals(session, storage.removeSessionByMappingId(TICKET)); @@ -114,7 +122,7 @@ public final class SingleSignOutHandlerTests { @Test public void destorySessionPOSTKONoSessionIndex() { - final String logoutMessage = LogoutMessageGenerator.generateLogoutMessage(""); + final String logoutMessage = LogoutMessageGenerator.generateBackChannelLogoutMessage(""); request.setParameter(logoutParameterName, logoutMessage); request.setMethod("POST"); final MockHttpSession session = new MockHttpSession(); @@ -125,7 +133,7 @@ public final class SingleSignOutHandlerTests { @Test public void destorySessionPOST() { - final String logoutMessage = LogoutMessageGenerator.generateLogoutMessage(TICKET); + final String logoutMessage = LogoutMessageGenerator.generateBackChannelLogoutMessage(TICKET); request.setParameter(logoutParameterName, logoutMessage); request.setMethod("POST"); final MockHttpSession session = new MockHttpSession(); @@ -136,9 +144,9 @@ public final class SingleSignOutHandlerTests { @Test public void destorySessionGETNoSessionIndex() { - final String logoutMessage = LogoutMessageGenerator.generateCompressedLogoutMessage(""); - request.setParameter(logoutParameterName, logoutMessage); - request.setQueryString(logoutParameterName + "=" + logoutMessage); + final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(""); + request.setParameter(frontLogoutParameterName, logoutMessage); + request.setQueryString(frontLogoutParameterName + "=" + logoutMessage); request.setMethod("GET"); final MockHttpSession session = new MockHttpSession(); handler.getSessionMappingStorage().addSessionById(TICKET, session); @@ -148,13 +156,26 @@ public final class SingleSignOutHandlerTests { @Test public void destorySessionGET() { - final String logoutMessage = LogoutMessageGenerator.generateCompressedLogoutMessage(TICKET); - request.setParameter(logoutParameterName, logoutMessage); - request.setQueryString(logoutParameterName + "=" + logoutMessage); + final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET); + request.setParameter(frontLogoutParameterName, logoutMessage); + request.setQueryString(frontLogoutParameterName + "=" + logoutMessage); request.setMethod("GET"); final MockHttpSession session = new MockHttpSession(); handler.getSessionMappingStorage().addSessionById(TICKET, session); handler.destroySession(request); assertTrue(session.isInvalid()); } + + @Test + public void computeRedirectionNoRelayState() { + assertNull(handler.computeRedirectionToServer(request)); + } + + @Test + public void computeRedirection() { + request.setParameter(relayStateParameterName, TICKET); + request.setQueryString(relayStateParameterName + "=" + TICKET); + assertEquals(URL + "/logout?_eventId=next&" + relayStateParameterName + "=" + TICKET, + handler.computeRedirectionToServer(request)); + } } diff --git a/cas-client-integration-tomcat-v6/src/main/java/org/jasig/cas/client/tomcat/v6/SingleSignOutValve.java b/cas-client-integration-tomcat-v6/src/main/java/org/jasig/cas/client/tomcat/v6/SingleSignOutValve.java index 1d95f43..d483e41 100644 --- a/cas-client-integration-tomcat-v6/src/main/java/org/jasig/cas/client/tomcat/v6/SingleSignOutValve.java +++ b/cas-client-integration-tomcat-v6/src/main/java/org/jasig/cas/client/tomcat/v6/SingleSignOutValve.java @@ -28,6 +28,7 @@ import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.jasig.cas.client.session.SessionMappingStorage; import org.jasig.cas.client.session.SingleSignOutHandler; +import org.jasig.cas.client.util.CommonUtils; /** * Handles logout request messages sent from the CAS server by ending the current @@ -52,6 +53,18 @@ public class SingleSignOutValve extends AbstractLifecycleValve implements Sessio handler.setLogoutParameterName(name); } + public void setFrontLogoutParameterName(final String name) { + handler.setFrontLogoutParameterName(name); + } + + public void setRelayStateParameterName(final String name) { + handler.setRelayStateParameterName(name); + } + + public void setCasServerUrlPrefix(final String casServerUrlPrefix) { + handler.setCasServerUrlPrefix(casServerUrlPrefix); + } + public void setSessionMappingStorage(final SessionMappingStorage storage) { handler.setSessionMappingStorage(storage); } @@ -68,10 +81,18 @@ public class SingleSignOutValve extends AbstractLifecycleValve implements Sessio if (this.handler.isTokenRequest(request)) { this.handler.recordSession(request); request.getSessionInternal(true).addSessionListener(this); - } else if (this.handler.isLogoutRequest(request)) { + } else if (this.handler.isBackChannelLogoutRequest(request)) { this.handler.destroySession(request); // Do not proceed up valve chain return; + } else if (this.handler.isFrontChannelLogoutRequest(request)) { + this.handler.destroySession(request); + // redirection url to the CAS server + final String redirectionUrl = handler.computeRedirectionToServer(request); + if (redirectionUrl != null) { + CommonUtils.sendRedirect(response, redirectionUrl); + } + return; } else { logger.debug("Ignoring URI {}", request.getRequestURI()); } diff --git a/cas-client-integration-tomcat-v7/src/main/java/org/jasig/cas/client/tomcat/v7/SingleSignOutValve.java b/cas-client-integration-tomcat-v7/src/main/java/org/jasig/cas/client/tomcat/v7/SingleSignOutValve.java index c1bee5b..8ecc865 100644 --- a/cas-client-integration-tomcat-v7/src/main/java/org/jasig/cas/client/tomcat/v7/SingleSignOutValve.java +++ b/cas-client-integration-tomcat-v7/src/main/java/org/jasig/cas/client/tomcat/v7/SingleSignOutValve.java @@ -29,6 +29,7 @@ import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; import org.jasig.cas.client.session.SessionMappingStorage; import org.jasig.cas.client.session.SingleSignOutHandler; +import org.jasig.cas.client.util.CommonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +57,18 @@ public class SingleSignOutValve extends ValveBase implements SessionListener { handler.setLogoutParameterName(name); } + public void setFrontLogoutParameterName(final String name) { + handler.setFrontLogoutParameterName(name); + } + + public void setRelayStateParameterName(final String name) { + handler.setRelayStateParameterName(name); + } + + public void setCasServerUrlPrefix(final String casServerUrlPrefix) { + handler.setCasServerUrlPrefix(casServerUrlPrefix); + } + public void setSessionMappingStorage(final SessionMappingStorage storage) { handler.setSessionMappingStorage(storage); } @@ -65,10 +78,18 @@ public class SingleSignOutValve extends ValveBase implements SessionListener { if (this.handler.isTokenRequest(request)) { this.handler.recordSession(request); request.getSessionInternal(true).addSessionListener(this); - } else if (this.handler.isLogoutRequest(request)) { + } else if (this.handler.isBackChannelLogoutRequest(request)) { this.handler.destroySession(request); // Do not proceed up valve chain return; + } else if (this.handler.isFrontChannelLogoutRequest(request)) { + this.handler.destroySession(request); + // redirection url to the CAS server + final String redirectionUrl = handler.computeRedirectionToServer(request); + if (redirectionUrl != null) { + CommonUtils.sendRedirect(response, redirectionUrl); + } + return; } else { logger.debug("Ignoring URI {}", request.getRequestURI()); }