package org.apereo.cas.web.flow;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.Authentication;
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
import org.apereo.cas.authentication.AuthenticationSystemSupport;
import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.consent.ConsentEngine;
import org.apereo.cas.consent.ConsentRepository;
import org.apereo.cas.services.RegisteredService;
import org.apereo.cas.services.RegisteredServiceAccessStrategyUtils;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.action.EventFactorySupport;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import java.util.Map;
/**
* This is {@link CheckConsentRequiredAction}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public class CheckConsentRequiredAction extends AbstractAction {
/**
* Indicates that webflow should proceed with consent.
*/
public static final String EVENT_ID_CONSENT_REQUIRED = "consentRequired";
private final ServicesManager servicesManager;
private final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies;
private final AuthenticationSystemSupport authenticationSystemSupport;
private final ConsentRepository consentRepository;
private final ConsentEngine consentEngine;
public CheckConsentRequiredAction(final ServicesManager servicesManager,
final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies,
final AuthenticationSystemSupport authenticationSystemSupport,
final ConsentRepository consentRepository,
final ConsentEngine consentEngine) {
this.servicesManager = servicesManager;
this.authenticationRequestServiceSelectionStrategies = authenticationRequestServiceSelectionStrategies;
this.authenticationSystemSupport = authenticationSystemSupport;
this.consentRepository = consentRepository;
this.consentEngine = consentEngine;
}
@Override
protected Event doExecute(final RequestContext requestContext) throws Exception {
final String consentEvent = determineConsentEvent(requestContext);
if (StringUtils.isBlank(consentEvent)) {
return null;
}
prepareConsentForRequestContext(requestContext);
return new EventFactorySupport().event(this, consentEvent);
}
private void prepareConsentForRequestContext(final RequestContext requestContext) {
final Service service = this.authenticationRequestServiceSelectionStrategies.resolveService(WebUtils.getService(requestContext));
final RegisteredService registeredService = getRegisteredServiceForConsent(requestContext, service);
final Authentication authentication = WebUtils.getAuthentication(requestContext);
final Map<String, Object> attributes =
registeredService.getAttributeReleasePolicy().getAttributes(authentication.getPrincipal(), service, registeredService);
requestContext.getFlowScope().put("attributes", attributes);
requestContext.getFlowScope().put("principal", authentication.getPrincipal().getId());
}
/**
* Determine consent event string.
*
* @param requestContext the request context
* @return the string
*/
protected String determineConsentEvent(final RequestContext requestContext) {
final Service service = this.authenticationRequestServiceSelectionStrategies.resolveService(WebUtils.getService(requestContext));
if (service == null) {
return null;
}
final RegisteredService registeredService = getRegisteredServiceForConsent(requestContext, service);
final Authentication authentication = WebUtils.getAuthentication(requestContext);
if (authentication == null) {
return null;
}
return isConsentRequired(service, registeredService, authentication, requestContext);
}
private RegisteredService getRegisteredServiceForConsent(final RequestContext requestContext, final Service service) {
RegisteredService registeredService = WebUtils.getRegisteredService(requestContext);
if (registeredService == null) {
registeredService = this.servicesManager.findServiceBy(service);
}
RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(service, registeredService);
return registeredService;
}
/**
* Is consent required ?
*
* @param service the service
* @param registeredService the registered service
* @param authentication the authentication
* @param requestContext the request context
* @return the event id.
*/
protected String isConsentRequired(final Service service, final RegisteredService registeredService,
final Authentication authentication, final RequestContext requestContext) {
final boolean required = this.consentEngine.isConsentRequiredFor(service, registeredService, authentication);
return required ? EVENT_ID_CONSENT_REQUIRED : null;
}
}