package org.apereo.cas.web.flow;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CasProtocolConstants;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.services.RegisteredService;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator;
import org.apereo.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Action that handles the TicketGrantingTicket creation and destruction. If the
* action is given a TicketGrantingTicket and one also already exists, the old
* one is destroyed and replaced with the new one. This action always returns
* "success".
*
* @author Scott Battaglia
* @since 3.0.0
*/
public class SendTicketGrantingTicketAction extends AbstractAction {
private static final Logger LOGGER = LoggerFactory.getLogger(SendTicketGrantingTicketAction.class);
private boolean createSsoSessionCookieOnRenewAuthentications = true;
private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
private CentralAuthenticationService centralAuthenticationService;
private ServicesManager servicesManager;
public SendTicketGrantingTicketAction(final CentralAuthenticationService centralAuthenticationService,
final ServicesManager servicesManager,
final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator,
final boolean renewedAuthn) {
super();
this.centralAuthenticationService = centralAuthenticationService;
this.servicesManager = servicesManager;
this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator;
this.createSsoSessionCookieOnRenewAuthentications = renewedAuthn;
}
@Override
protected Event doExecute(final RequestContext context) {
final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
final String ticketGrantingTicketValueFromCookie = (String) context.getFlowScope().get("ticketGrantingTicketId");
final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
final HttpServletResponse response = WebUtils.getHttpServletResponse(context);
if (StringUtils.isBlank(ticketGrantingTicketId)) {
LOGGER.debug("No ticket-granting ticket is found in the context.");
return success();
}
if (WebUtils.isAuthenticatingAtPublicWorkstation(context)) {
LOGGER.info("Authentication is at a public workstation. SSO cookie will not be generated. Requests will be challenged for authentication.");
} else if (!this.createSsoSessionCookieOnRenewAuthentications && isAuthenticationRenewed(context)) {
LOGGER.info("Authentication session is renewed but CAS is not configured to create the SSO session. "
+ "SSO cookie will not be generated. Subsequent requests will be challenged for credentials.");
} else {
LOGGER.debug("Setting TGC for current session linked to [{}].", ticketGrantingTicketId);
this.ticketGrantingTicketCookieGenerator.addCookie(request, response, ticketGrantingTicketId);
}
if (ticketGrantingTicketValueFromCookie != null && !ticketGrantingTicketId.equals(ticketGrantingTicketValueFromCookie)) {
LOGGER.debug("Ticket-granting ticket from TGC does not match the ticket-granting ticket from context");
this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketValueFromCookie);
}
return success();
}
/**
* Tries to determine if authentication was created as part of a "renew" event.
* Renewed authentications can occur if the service is not allowed to participate
* in SSO or if a "renew" request parameter is specified.
*
* @param ctx the request context
* @return true if renewed
*/
private boolean isAuthenticationRenewed(final RequestContext ctx) {
if (ctx.getRequestParameters().contains(CasProtocolConstants.PARAMETER_RENEW)) {
LOGGER.debug("[{}] is specified for the request. The authentication session will be considered renewed.", CasProtocolConstants.PARAMETER_RENEW);
return true;
}
final Service service = WebUtils.getService(ctx);
if (service != null) {
final RegisteredService registeredService = this.servicesManager.findServiceBy(service);
if (registeredService != null) {
final boolean isAllowedForSso = registeredService.getAccessStrategy().isServiceAccessAllowedForSso();
LOGGER.debug("Located [{}] in registry. Service access to participate in SSO is set to [{}]",
registeredService.getServiceId(), isAllowedForSso);
return !isAllowedForSso;
}
}
return false;
}
}