package org.apereo.cas.authentication;
import org.apereo.cas.authentication.principal.Principal;
import org.springframework.core.Ordered;
import java.security.GeneralSecurityException;
/**
* An authentication handler authenticates a single credential. In many cases credentials are authenticated by
* comparison with data in a system of record such as LDAP directory or database.
*
* @author Marvin S. Addison
* @since 4.0.0
*/
public interface AuthenticationHandler extends Ordered {
/** Attribute name containing collection of handler names that successfully authenticated credential. */
String SUCCESSFUL_AUTHENTICATION_HANDLERS = "successfulAuthenticationHandlers";
/**
* Authenticates the given credential. There are three possible outcomes of this process, and implementers
* MUST adhere to the following contract:
*
* <ol>
* <li>Success -- return {@link HandlerResult}</li>
* <li>Failure -- throw {@link GeneralSecurityException}</li>
* <li>Indeterminate -- throw {@link PreventedException}</li>
* </ol>
*
* @param credential The credential to authenticate.
*
* @return A result object containing metadata about a successful authentication event that includes at
* a minimum the name of the handler that authenticated the credential and some credential metadata.
* The following data is optional:
* <ul>
* <li>{@link Principal}</li>
* <li>Messages issued by the handler about the credential (e.g. impending password expiration warning)</li>
* </ul>
*
* @throws GeneralSecurityException On authentication failures where the root cause is security related,
* e.g. invalid credential. Implementing classes SHOULD be as specific as possible in communicating the reason for
* authentication failure. Recommendations for common cases:
* <ul>
* <li>Bad password: {@code javax.security.auth.login.FailedLoginException}</li>
* <li>Expired password: {@code javax.security.auth.login.CredentialExpiredException}</li>
* <li>User account expired: {@code javax.security.auth.login.AccountExpiredException}</li>
* <li>User account locked: {@code javax.security.auth.login.AccountLockedException}</li>
* <li>User account not found: {@code javax.security.auth.login.AccountNotFoundException}</li>
* <li>Time of authentication not allowed: {@code org.apereo.cas.authentication.InvalidLoginTimeException}</li>
* <li>Location of authentication not allowed: {@code org.apereo.cas.authentication.InvalidLoginLocationException}</li>
* <li>Expired X.509 certificate: {@code java.security.cert.CertificateExpiredException}</li>
* </ul>
* @throws PreventedException On errors that prevented authentication from occurring. Implementing classes SHOULD
* take care to populate the cause, where applicable, with the error that prevented authentication.
*/
HandlerResult authenticate(Credential credential) throws GeneralSecurityException, PreventedException;
/**
* Determines whether the handler has the capability to authenticate the given credential. In practical terms,
* the {@link #authenticate(Credential)} method MUST be capable of processing a given credential if
* {@code supports} returns true on the same credential.
*
* @param credential The credential to check.
*
* @return True if the handler supports the Credential, false otherwise.
*/
boolean supports(Credential credential);
/**
* Gets a unique name for this authentication handler within the Spring context that contains it.
* For implementations that allow setting a unique name, deployers MUST take care to ensure that every
* handler instance has a unique name.
*
* @return Unique name within a Spring context.
*/
String getName();
}