package org.apereo.cas.web.flow;
import org.apereo.cas.authentication.AuthenticationException;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.authentication.adaptive.UnauthorizedAuthenticationException;
import org.apereo.cas.authentication.adaptive.geo.GeoLocationRequest;
import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver;
import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import java.util.Collections;
import java.util.Map;
/**
* This is {@link AbstractAuthenticationAction}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public abstract class AbstractAuthenticationAction extends AbstractAction {
private final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver;
private final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;
private final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver;
public AbstractAuthenticationAction(final CasDelegatingWebflowEventResolver delegatingWebflowEventResolver,
final CasWebflowEventResolver webflowEventResolver,
final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy) {
this.initialAuthenticationAttemptWebflowEventResolver = delegatingWebflowEventResolver;
this.serviceTicketRequestWebflowEventResolver = webflowEventResolver;
this.adaptiveAuthenticationPolicy = adaptiveAuthenticationPolicy;
}
@Override
protected Event doExecute(final RequestContext requestContext) throws Exception {
final String agent = WebUtils.getHttpServletRequestUserAgent();
final GeoLocationRequest geoLocation = WebUtils.getHttpServletRequestGeoLocation();
if (!adaptiveAuthenticationPolicy.apply(agent, geoLocation)) {
final String msg = "Adaptive authentication policy does not allow this request for " + agent + " and " + geoLocation;
final Map<String, Class<? extends Exception>> map = Collections.singletonMap(
UnauthorizedAuthenticationException.class.getSimpleName(),
UnauthorizedAuthenticationException.class);
final AuthenticationException error = new AuthenticationException(msg, map, Collections.emptyMap());
return new Event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE,
new LocalAttributeMap(CasWebflowConstants.TRANSITION_ID_ERROR, error));
}
final Event serviceTicketEvent = this.serviceTicketRequestWebflowEventResolver.resolveSingle(requestContext);
if (serviceTicketEvent != null) {
fireEventHooks(serviceTicketEvent, requestContext);
return serviceTicketEvent;
}
final Event finalEvent = this.initialAuthenticationAttemptWebflowEventResolver.resolveSingle(requestContext);
fireEventHooks(finalEvent, requestContext);
return finalEvent;
}
private void fireEventHooks(final Event e, final RequestContext ctx) {
if (e.getId().equals(CasWebflowConstants.TRANSITION_ID_ERROR)) {
onError(ctx);
}
if (e.getId().equals(CasWebflowConstants.TRANSITION_ID_WARN)) {
onWarn(ctx);
}
if (e.getId().equals(CasWebflowConstants.TRANSITION_ID_SUCCESS)) {
onSuccess(ctx);
}
}
/**
* On warn.
*
* @param context the context
*/
protected void onWarn(final RequestContext context) {}
/**
* On success.
*
* @param context the context
*/
protected void onSuccess(final RequestContext context) {}
/**
* On error.
*
* @param context the context
*/
protected void onError(final RequestContext context) {}
}