/*
* See LICENSE for licensing and NOTICE for copyright.
*/
package net.shibboleth.idp.cas.flow;
import net.shibboleth.idp.cas.protocol.ProtocolError;
import net.shibboleth.idp.cas.protocol.ProtocolParam;
import net.shibboleth.idp.cas.protocol.ProxyTicketRequest;
import net.shibboleth.idp.cas.ticket.ProxyGrantingTicket;
import net.shibboleth.idp.cas.ticket.TicketContext;
import net.shibboleth.idp.cas.ticket.TicketService;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.ActionSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.core.collection.ParameterMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import javax.annotation.Nonnull;
/**
* Initializes the CAS protocol interaction at the <code>/proxy</code> URI and returns one of the following events:
*
* <ul>
* <li>{@link net.shibboleth.idp.cas.flow.Events#Proceed proceed}</li>
* <li>{@link net.shibboleth.idp.cas.protocol.ProtocolError#ServiceNotSpecified serviceNotSpecified}</li>
* <li>{@link net.shibboleth.idp.cas.protocol.ProtocolError#TicketNotSpecified ticketNotSpecified}</li>
* <li>{@link net.shibboleth.idp.cas.protocol.ProtocolError#TicketRetrievalError ticketRetrievalError}</li>
* </ul>
*
* On proceed places a {@link net.shibboleth.idp.cas.protocol.ProxyTicketRequest} object in request scope under the key
* {@value net.shibboleth.idp.cas.flow.FlowStateSupport#PROXY_TICKET_REQUEST_KEY}. Also creates a {@link TicketContext}
* containing the PGT provided to the <code>/proxy</code> endpoint and places it under the
* {@link org.opensaml.profile.context.ProfileRequestContext}.
*
* @author Marvin S. Addison
*/
public class InitializeProxyAction extends AbstractProfileAction {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(InitializeProxyAction.class);
/** Manages CAS tickets. */
@Nonnull private TicketService ticketService;
public void setTicketService(@Nonnull final TicketService ticketService) {
this.ticketService = Constraint.isNotNull(ticketService, "Ticket service cannot be null.");
}
@Nonnull
@Override
protected Event doExecute(
final @Nonnull RequestContext springRequestContext,
final @Nonnull ProfileRequestContext profileRequestContext) {
final ParameterMap params = springRequestContext.getRequestParameters();
final String service = params.get(ProtocolParam.TargetService.id());
if (service == null) {
return ProtocolError.ServiceNotSpecified.event(this);
}
final String ticket = params.get(ProtocolParam.Pgt.id());
if (ticket == null) {
return ProtocolError.TicketNotSpecified.event(this);
}
final ProxyTicketRequest proxyTicketRequest = new ProxyTicketRequest(ticket, service);
final MessageContext messageContext = new MessageContext();
messageContext.setMessage(proxyTicketRequest);
profileRequestContext.setInboundMessageContext(messageContext);
FlowStateSupport.setProxyTicketRequest(springRequestContext, proxyTicketRequest);
try {
log.debug("Fetching proxy-granting ticket {}", proxyTicketRequest.getPgt());
profileRequestContext.addSubcontext(
new TicketContext(ticketService.fetchProxyGrantingTicket(proxyTicketRequest.getPgt())));
} catch (RuntimeException e) {
log.error("Failed looking up " + proxyTicketRequest.getPgt(), e);
return ProtocolError.TicketRetrievalError.event(this);
}
return ActionSupport.buildProceedEvent(this);
}
}