package org.apereo.cas.authentication;
import org.apache.commons.codec.binary.StringUtils;
import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Handler that contains a list of valid users and passwords. Useful if there is
* a small list of users that we wish to allow. An example use case may be if
* there are existing handlers that make calls to LDAP, etc. but there is a need
* for additional users we don't want in LDAP. With the chain of command
* processing of handlers, this handler could be added to check before LDAP and
* provide the list of additional users. The list of acceptable users is stored
* in a map. The key of the map is the username and the password is the object
* retrieved from doing map.get(KEY).
*
* @author Scott Battaglia
* @author Marvin S. Addison
* @since 3.0.0
*/
public class AcceptUsersAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(AcceptUsersAuthenticationHandler.class);
/**
* The list of users we will accept.
*/
private Map<String, String> users;
/**
* Instantiates a new Accept users authentication handler.
*
* @param name the name
*/
public AcceptUsersAuthenticationHandler(final String name) {
this(name, null, null, null, new HashMap<>());
}
/**
* Instantiates a new Accept users authentication handler.
*
* @param name the name
* @param servicesManager the services manager
* @param principalFactory the principal factory
* @param order the order
* @param users the users
*/
public AcceptUsersAuthenticationHandler(final String name, final ServicesManager servicesManager, final PrincipalFactory principalFactory,
final Integer order, final Map<String, String> users) {
super(name, servicesManager, principalFactory, order);
this.users = users;
}
@Override
protected HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential,
final String originalPassword)
throws GeneralSecurityException, PreventedException {
if (this.users == null || this.users.isEmpty()) {
throw new FailedLoginException("No user can be accepted because none is defined");
}
final String username = credential.getUsername();
final String cachedPassword = this.users.get(username);
if (cachedPassword == null) {
LOGGER.debug("[{}] was not found in the map.", username);
throw new AccountNotFoundException(username + " not found in backing map.");
}
if (!StringUtils.equals(credential.getPassword(), cachedPassword)) {
throw new FailedLoginException();
}
final List<MessageDescriptor> list = new ArrayList<>();
return createHandlerResult(credential, this.principalFactory.createPrincipal(username), list);
}
/**
* @param users The users to set.
*/
public void setUsers(final Map<String, String> users) {
this.users = new HashMap<>(users);
}
}