package org.apereo.cas.web.flow; import org.apereo.cas.logout.LogoutHttpMessage; import org.apereo.cas.logout.LogoutManager; import org.apereo.cas.logout.LogoutRequest; import org.apereo.cas.logout.LogoutRequestStatus; import org.apereo.cas.web.support.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.webflow.action.EventFactorySupport; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Logout action for front SLO : find the next eligible service and perform front logout. * * @author Jerome Leleu * @since 4.0.0 */ public class FrontChannelLogoutAction extends AbstractLogoutAction { private static final Logger LOGGER = LoggerFactory.getLogger(FrontChannelLogoutAction.class); private LogoutManager logoutManager; /** * Build from the logout manager. * * @param logoutManager a logout manager. */ public FrontChannelLogoutAction(final LogoutManager logoutManager) { this.logoutManager = logoutManager; } @Override protected Event doInternalExecute(final HttpServletRequest request, final HttpServletResponse response, final RequestContext context) throws Exception { final List<LogoutRequest> logoutRequests = WebUtils.getLogoutRequests(context); final Map<LogoutRequest, LogoutHttpMessage> logoutUrls = new HashMap<>(); if (logoutRequests != null) { logoutRequests.stream() .filter(r -> r.getStatus() == LogoutRequestStatus.NOT_ATTEMPTED) .forEach(r -> { LOGGER.debug("Using logout url [{}] for front-channel logout requests", r.getLogoutUrl().toExternalForm()); final String logoutMessage = this.logoutManager.createFrontChannelLogoutMessage(r); LOGGER.debug("Front-channel logout message to send is [{}]", logoutMessage); final LogoutHttpMessage msg = new LogoutHttpMessage(r.getLogoutUrl(), logoutMessage, true); logoutUrls.put(r, msg); r.setStatus(LogoutRequestStatus.SUCCESS); r.getService().setLoggedOutAlready(true); }); if (!logoutUrls.isEmpty()) { context.getFlowScope().put("logoutUrls", logoutUrls); return new EventFactorySupport().event(this, "propagate"); } } return new EventFactorySupport().event(this, FINISH_EVENT); } }