org.apereo.cas.web.flow.DelegatedAuthenticationSAML2ClientLogoutAction Maven / Gradle / Ivy
Show all versions of cas-server-support-pac4j-webflow Show documentation
package org.apereo.cas.web.flow;
import org.apereo.cas.util.Pac4jUtils;
import org.apereo.cas.web.support.WebUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.pac4j.core.client.Client;
import org.pac4j.core.client.Clients;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.saml.client.SAML2Client;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import java.util.Optional;
/**
* This is {@link DelegatedAuthenticationSAML2ClientLogoutAction}.
*
* The action takes into account the currently used PAC4J client which is stored
* in the user profile. If the client is not a SAML2 client, nothing happens. If
* it is a SAML2 client, its logout action is executed.
*
* Assumption: The PAC4J user profile should be in the user session during
* logout, accessible with PAC4J Profile Manager. The Logout web flow should
* make sure the user profile is present.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
@Slf4j
@RequiredArgsConstructor
public class DelegatedAuthenticationSAML2ClientLogoutAction extends AbstractAction {
private final Clients clients;
@Override
protected Event doExecute(final RequestContext requestContext) {
try {
val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(requestContext);
val context = Pac4jUtils.getPac4jJ2EContext(request, response);
Client, ?> client;
try {
val currentClientName = findCurrentClientName(context);
client = currentClientName == null ? null : clients.findClient(currentClientName);
} catch (final TechnicalException e) {
LOGGER.debug("No SAML2 client found: " + e.getMessage(), e);
client = null;
}
if (client instanceof SAML2Client) {
val saml2Client = (SAML2Client) client;
LOGGER.debug("Located SAML2 client [{}]", saml2Client);
val action = saml2Client.getLogoutAction(context, null, null);
LOGGER.debug("Preparing logout message to send is [{}]", action.getLocation());
action.perform(context);
} else {
LOGGER.debug("The current client is not a SAML2 client or it cannot be found at all, no logout action will be executed.");
}
} catch (final Exception e) {
LOGGER.warn(e.getMessage(), e);
}
return null;
}
/**
* Finds the current client name from the context, using the PAC4J Profile Manager. It is assumed that the context has previously been
* populated with the profile.
*
* @param webContext A web context (request + response).
* @return The currently used client's name or {@code null} if there is no active profile.
*/
private static String findCurrentClientName(final WebContext webContext) {
val pm = Pac4jUtils.getPac4jProfileManager(webContext);
val profile = (Optional) pm.get(true);
return profile.map(CommonProfile::getClientName).orElse(null);
}
}