package org.apereo.cas.authentication.handler.support;
import org.apereo.cas.authentication.AbstractAuthenticationHandler;
import org.apereo.cas.authentication.exceptions.AccountDisabledException;
import org.apereo.cas.authentication.BasicCredentialMetaData;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.DefaultHandlerResult;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.exceptions.InvalidLoginLocationException;
import org.apereo.cas.authentication.exceptions.InvalidLoginTimeException;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.CredentialExpiredException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
/**
* Simple test implementation of a AuthenticationHandler that returns true if
* the username and password match. This class should never be enabled in a
* production environment and is only designed to facilitate unit testing and
* load testing.
*
* @author Scott Battagliaa
* @author Marvin S. Addison
* @since 3.0.0
*/
public class SimpleTestUsernamePasswordAuthenticationHandler extends AbstractAuthenticationHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTestUsernamePasswordAuthenticationHandler.class);
/**
* Default mapping of special usernames to exceptions raised when that user attempts authentication.
*/
private static final Map<String, Exception> DEFAULT_USERNAME_ERROR_MAP = new HashMap<>();
protected PrincipalFactory principalFactory = new DefaultPrincipalFactory();
/**
* Map of special usernames to exceptions that are raised when a user with that name attempts authentication.
*/
private Map<String, Exception> usernameErrorMap = DEFAULT_USERNAME_ERROR_MAP;
static {
DEFAULT_USERNAME_ERROR_MAP.put("accountDisabled", new AccountDisabledException("Account disabled"));
DEFAULT_USERNAME_ERROR_MAP.put("accountLocked", new AccountLockedException("Account locked"));
DEFAULT_USERNAME_ERROR_MAP.put("badHours", new InvalidLoginTimeException("Invalid logon hours"));
DEFAULT_USERNAME_ERROR_MAP.put("badWorkstation", new InvalidLoginLocationException("Invalid workstation"));
DEFAULT_USERNAME_ERROR_MAP.put("passwordExpired", new CredentialExpiredException("Password expired"));
}
public SimpleTestUsernamePasswordAuthenticationHandler() {
super("", null, null, null);
}
@PostConstruct
private void init() {
LOGGER.warn("[{}] is only to be used in a testing environment. NEVER enable this in a production environment.",
this.getClass().getName());
}
@Override
public HandlerResult authenticate(final Credential credential)
throws GeneralSecurityException, PreventedException {
final UsernamePasswordCredential usernamePasswordCredential = (UsernamePasswordCredential) credential;
final String username = usernamePasswordCredential.getUsername();
final String password = usernamePasswordCredential.getPassword();
final Exception exception = this.usernameErrorMap.get(username);
if (exception instanceof GeneralSecurityException) {
throw (GeneralSecurityException) exception;
}
if (exception instanceof PreventedException) {
throw (PreventedException) exception;
}
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
}
if (exception != null) {
LOGGER.debug("Cannot throw checked exception [{}] since it is not declared by method signature.",
exception.getClass().getName(),
exception);
}
if (StringUtils.hasText(username) && StringUtils.hasText(password) && username.equals(password)) {
LOGGER.debug("User [{}] was successfully authenticated.", username);
return new DefaultHandlerResult(this, new BasicCredentialMetaData(credential),
this.principalFactory.createPrincipal(username));
}
LOGGER.debug("User [{}] failed authentication", username);
throw new FailedLoginException();
}
@Override
public boolean supports(final Credential credential) {
return credential instanceof UsernamePasswordCredential;
}
}