org.dspace.authenticate.PasswordAuthentication Maven / Gradle / Ivy
Show all versions of dspace-api Show documentation
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.authenticate;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.core.Context;
import org.dspace.core.LogHelper;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.services.factory.DSpaceServicesFactory;
/**
* A stackable authentication method
* based on the DSpace internal "EPerson" database.
* See the AuthenticationMethod
interface for more details.
*
* The username is the E-Person's email address,
* and and the password (given to the authenticate()
* method) must match the EPerson password.
*
* This is the default method for a new DSpace configuration.
* If you are implementing a new "explicit" authentication method,
* use this class as a model.
*
* You can use this (or another explicit) method in the stack to
* implement HTTP Basic Authentication for servlets, by passing the
* Basic Auth username and password to the AuthenticationManager
.
*
* @author Larry Stone
*/
public class PasswordAuthentication
implements AuthenticationMethod {
/**
* log4j category
*/
private static final Logger log = LogManager.getLogger();
/**
* Look to see if this email address is allowed to register.
*
* The configuration key domain.valid is examined
* in authentication-password.cfg to see what domains are valid.
*
* Example - aber.ac.uk domain : @aber.ac.uk
* Example - MIT domain and all .ac.uk domains: @mit.edu, .ac.uk
*
* @param email email
* @throws SQLException if database error
*/
@Override
public boolean canSelfRegister(Context context,
HttpServletRequest request,
String email)
throws SQLException {
// Is there anything set in domain.valid?
String[] domains = DSpaceServicesFactory.getInstance().getConfigurationService()
.getArrayProperty("authentication-password.domain.valid");
if ((domains == null) || (domains.length == 0)) {
// No conditions set, so must be able to self register
return true;
} else {
// Itterate through all domains
String check;
email = email.trim().toLowerCase();
for (int i = 0; i < domains.length; i++) {
check = domains[i].trim().toLowerCase();
if (email.endsWith(check)) {
// A match, so we can register this user
return true;
}
}
// No match
return false;
}
}
/**
* Nothing extra to initialize.
*
* @throws SQLException if database error
*/
@Override
public void initEPerson(Context context, HttpServletRequest request,
EPerson eperson)
throws SQLException {
}
/**
* We always allow the user to change their password.
*
* @throws SQLException if database error
*/
@Override
public boolean allowSetPassword(Context context,
HttpServletRequest request,
String username)
throws SQLException {
return true;
}
/**
* This is an explicit method, since it needs username and password
* from some source.
*
* @return false
*/
@Override
public boolean isImplicit() {
return false;
}
/**
* Add authenticated users to the group defined in authentication-password.cfg by
* the login.specialgroup key.
*/
@Override
public List getSpecialGroups(Context context, HttpServletRequest request) {
// Prevents anonymous users from being added to this group, and the second check
// ensures they are password users
try {
if (context.getCurrentUser() != null
&& StringUtils.isNotBlank(
EPersonServiceFactory.getInstance().getEPersonService().getPasswordHash(context.getCurrentUser())
.toString())) {
String groupName = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("authentication-password.login.specialgroup");
if ((groupName != null) && !groupName.trim().isEmpty()) {
Group specialGroup = EPersonServiceFactory.getInstance().getGroupService()
.findByName(context, groupName);
if (specialGroup == null) {
// Oops - the group isn't there.
log.warn(LogHelper.getHeader(context,
"password_specialgroup",
"Group defined in modules/authentication-password.cfg login" +
".specialgroup does not exist"));
return Collections.EMPTY_LIST;
} else {
return Arrays.asList(specialGroup);
}
}
}
} catch (Exception e) {
log.error(LogHelper.getHeader(context, "getSpecialGroups", ""), e);
}
return Collections.EMPTY_LIST;
}
/**
* Check credentials: username must match the email address of an
* EPerson record, and that EPerson must be allowed to login.
* Password must match its password. Also checks for EPerson that
* is only allowed to login via an implicit method
* and returns CERT_REQUIRED
if that is the case.
*
* @param context DSpace context, will be modified (EPerson set) upon success.
* @param username Username (or email address) when method is explicit. Use null for
* implicit method.
* @param password Password for explicit auth, or null for implicit method.
* @param realm Realm is an extra parameter used by some authentication methods, leave null if
* not applicable.
* @param request The HTTP request that started this operation, or null if not applicable.
* @return One of:
* SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS
* Meaning:
*
SUCCESS - authenticated OK.
*
BAD_CREDENTIALS - user exists, but password doesn't match
*
CERT_REQUIRED - not allowed to login this way without X.509 cert.
*
NO_SUCH_USER - no EPerson with matching email address.
*
BAD_ARGS - missing username, or user matched but cannot login.
* @throws SQLException if database error
*/
@Override
public int authenticate(Context context,
String username,
String password,
String realm,
HttpServletRequest request)
throws SQLException {
if (username != null && password != null) {
EPerson eperson = null;
log.info(LogHelper.getHeader(context, "authenticate", "attempting password auth of user=" + username));
eperson = EPersonServiceFactory.getInstance().getEPersonService()
.findByEmail(context, username.toLowerCase());
if (eperson == null) {
// lookup failed.
return NO_SUCH_USER;
} else if (!eperson.canLogIn()) {
// cannot login this way
return BAD_ARGS;
} else if (eperson.getRequireCertificate()) {
// this user can only login with x.509 certificate
log.warn(LogHelper.getHeader(context, "authenticate",
"rejecting PasswordAuthentication because " + username + " requires " +
"certificate."));
return CERT_REQUIRED;
} else if (EPersonServiceFactory.getInstance().getEPersonService()
.checkPassword(context, eperson, password)) {
// login is ok if password matches:
context.setCurrentUser(eperson);
log.info(LogHelper.getHeader(context, "authenticate", "type=PasswordAuthentication"));
return SUCCESS;
} else {
return BAD_CREDENTIALS;
}
} else {
// BAD_ARGS always defers to the next authentication method.
// It means this method cannot use the given credentials.
return BAD_ARGS;
}
}
/**
* Returns URL of password-login servlet.
*
* @param context DSpace context, will be modified (EPerson set) upon success.
* @param request The HTTP request that started this operation, or null if not applicable.
* @param response The HTTP response from the servlet method.
* @return fully-qualified URL
*/
@Override
public String loginPageURL(Context context,
HttpServletRequest request,
HttpServletResponse response) {
return null;
}
@Override
public String getName() {
return "password";
}
}