package org.apereo.cas.trusted.web.flow; import org.apereo.cas.authentication.Authentication; import org.apereo.cas.configuration.model.support.mfa.MultifactorAuthenticationProperties; import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustRecord; import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustStorage; import org.apereo.cas.trusted.util.MultifactorAuthenticationTrustUtils; import org.apereo.cas.util.DateTimeUtils; 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 java.time.LocalDate; import java.util.Set; /** * This is {@link MultifactorAuthenticationVerifyTrustAction}. * * @author Misagh Moayyed * @since 5.0.0 */ public class MultifactorAuthenticationVerifyTrustAction extends AbstractAction { private static final Logger LOGGER = LoggerFactory.getLogger(MultifactorAuthenticationVerifyTrustAction.class); private final MultifactorAuthenticationTrustStorage storage; private final MultifactorAuthenticationProperties.Trusted trustedProperties; public MultifactorAuthenticationVerifyTrustAction(final MultifactorAuthenticationTrustStorage storage, final MultifactorAuthenticationProperties.Trusted trustedProperties) { this.storage = storage; this.trustedProperties = trustedProperties; } @Override protected Event doExecute(final RequestContext requestContext) throws Exception { final Authentication c = WebUtils.getAuthentication(requestContext); if (c == null) { LOGGER.warn("Could not determine authentication from the request context"); return no(); } final String principal = c.getPrincipal().getId(); final LocalDate onOrAfter = LocalDate.now().minus(trustedProperties.getExpiration(), DateTimeUtils.toChronoUnit(trustedProperties.getTimeUnit())); LOGGER.warn("Retrieving trusted authentication records for [{}] that are on/after [{}]", principal, onOrAfter); final Set<MultifactorAuthenticationTrustRecord> results = storage.get(principal, onOrAfter); if (results.isEmpty()) { LOGGER.debug("No valid trusted authentication records could be found for [{}]", principal); return no(); } final String geography = MultifactorAuthenticationTrustUtils.generateGeography(); LOGGER.debug("Retrieving authentication records for [{}] that match [{}]", principal, geography); if (results.stream() .noneMatch(entry -> entry.getGeography().equals(geography))) { LOGGER.debug("No trusted authentication records could be found for [{}] to match the current geography", principal); return no(); } LOGGER.debug("Trusted authentication records found for [{}] that matches the current geography", principal); MultifactorAuthenticationTrustUtils.setMultifactorAuthenticationTrustedInScope(requestContext); MultifactorAuthenticationTrustUtils.trackTrustedMultifactorAuthenticationAttribute( c, trustedProperties.getAuthenticationContextAttribute()); return yes(); } }