package org.apereo.cas.authentication.policy; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.authentication.Authentication; import org.apereo.cas.authentication.AuthenticationPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Authentication security policy that is satisfied iff a specified authentication handler successfully authenticates * at least one credential. * * @author Marvin S. Addison * @since 4.0.0 */ public class RequiredHandlerAuthenticationPolicy implements AuthenticationPolicy { private static final Logger LOGGER = LoggerFactory.getLogger(RequiredHandlerAuthenticationPolicy.class); /** * Authentication handler name that is required to satisfy policy. */ private final String requiredHandlerName; /** * Flag to try all credentials before policy is satisfied. */ private final boolean tryAll; /** * Instantiates a new required handler authentication policy. * * @param requiredHandlerName the required handler name */ public RequiredHandlerAuthenticationPolicy(final String requiredHandlerName) { this(requiredHandlerName, false); } /** * Instantiates a new Required handler authentication policy. * * @param requiredHandlerName the required handler name * @param tryAll Sets the flag to try all credentials before the policy is satisfied. * This flag is disabled by default such that the policy is satisfied immediately upon the first * credential that is successfully authenticated by the required handler. */ public RequiredHandlerAuthenticationPolicy(final String requiredHandlerName, final boolean tryAll) { this.requiredHandlerName = requiredHandlerName; this.tryAll = tryAll; } @Override public boolean isSatisfiedBy(final Authentication authn) { boolean credsOk = true; if (this.tryAll) { credsOk = authn.getCredentials().size() == authn.getSuccesses().size() + authn.getFailures().size(); } if (!credsOk) { LOGGER.warn("Number of provided credentials does not match the sum of authentication successes and failures"); return false; } LOGGER.debug("Examining authentication successes for authentication handler [{}]", this.requiredHandlerName); if (StringUtils.isNotBlank(this.requiredHandlerName)) { credsOk = authn.getSuccesses().keySet() .stream() .filter(s -> s.equalsIgnoreCase(this.requiredHandlerName)) .findAny() .isPresent(); if (!credsOk) { LOGGER.warn("Required authentication handler [{}] is not present in the list of recorded successful authentications", this.requiredHandlerName); return false; } } LOGGER.debug("Authentication policy is satisfied"); return true; } }