/**
*
*/
package org.dspace.authenticate;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.dspace.authenticate.LDAPAuthentication.SpeakerToLDAP;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
/**
* @author Ian Fieldhouse
*
*/
public class EdiauthAuthentication implements AuthenticationMethod {
private static final String JORUMUK_USER_SERVICE = "jorum";
private static final String EA_SERVICES = "ea_services";
private static final String JORUMUK_USER_GROUP = "JorumUKUser";
/** log4j category */
private static Logger log = Logger.getLogger(EdiauthAuthentication.class);
/**
* This is an explicit method as it require
* a shibbid from some source
*
* @return false
*/
public boolean isImplicit() {
return false;
}
/**
* Returns message key for title of the "login" page, to use
* in a menu showing the choice of multiple login methods.
*
* @param context
* DSpace context, will be modified (EPerson set) upon success.
*
* @return Message key to look up in i18n message catalog.
*/
public String loginPageTitle(Context context)
{
return "org.dspace.eperson.EdiauthAuthentication.title";
}
/**
* Returns URL of ediauth-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
*/
public String loginPageURL(Context context,
HttpServletRequest request,
HttpServletResponse response)
{
return response.encodeRedirectURL(request.getContextPath() + "/ediauth-login");
}
/**
* Allow new users to be registered automatically if the Ediauth
* server provides sufficient info (and user not exists in DSpace)
*
* @param context
* DSpace context
* @param request
* HTTP request, in case anything in that is used to decide
* @param email
* e-mail address of user attempting to register
* @return Property from dspace.cfg file
*/
public boolean canSelfRegister(Context context,
HttpServletRequest request,
String username)
throws SQLException
{
return ConfigurationManager.getBooleanProperty("authentication.ediauth.autoregister");
}
/**
* Indicate whether or not a particular self-registering user can set
* themselves a password in the profile info form.
*
* @param context
* DSpace context
* @param request
* HTTP request, in case anything in that is used to decide
* @param email
* e-mail address of user attempting to register
* @return Users cannot set their own passwords
*
*/
public boolean allowSetPassword(Context context,
HttpServletRequest request,
String email)
throws SQLException
{
return false;
}
/**
* Add authenticated users to the group defined in dspace.cfg by
* the ediauth.login.specialgroup key.
*
* @param context
* DSpace context
* @param request
* HTTP request, in case anything in that is used to decide
* @return Special group id
*/
public int[] getSpecialGroups(Context context,
HttpServletRequest request)
{
// Prevents non-ediauth users from being added to this group
try
{
if (!context.getCurrentUser().getNetid().equals(""))
{
String groupName = ConfigurationManager.getProperty("ediauth.login.specialgroup");
if ((groupName != null) && (!groupName.trim().equals("")))
{
Group specialGroup = Group.findByName(context, groupName);
if (specialGroup == null)
{
// Oops - the group isn't there.
log.warn(LogManager.getHeader(context,
"ediauth_specialgroup",
"Group defined in password.ediauth.specialgroup does not exist"));
return new int[0];
} else
{
return new int[] { specialGroup.getID() };
}
}
}
}
catch (Exception e) {
// The user is not an ediauth user, so we don't need to worry about them
}
return new int[0];
}
/**
* Check credentials: shibbid must match the netid of an EPerson record,
* and that EPerson must be allowed to login. Also checks for EPerson that
* is only allowed to login via an implicit method and returns <code>CERT_REQUIRED</code>
* if that is the case.
*
* @param context
* DSpace context, will be modified (EPerson set) upon success.
*
* @param shibbid
* Shibboleth ID when method is explicit. Use null for implicit method.
*
* @param password
* Null for both explicit and implicit methods.
*
* @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, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS
* <p>Meaning:
* <br>SUCCESS - authenticated OK.
* <br>CERT_REQUIRED - not allowed to login this way without X.509 cert.
* <br>NO_SUCH_USER - no EPerson with matching email address.
* <br>BAD_ARGS - missing shibbid, or user matched but cannot login.
*/
public int authenticate(Context context,
String shibbid,
String password,
String realm,
HttpServletRequest request)
throws SQLException
{
log.info(LogManager.getHeader(context, "auth", "attempting authentication of user="+shibbid));
// Return BAD_ARGS when no shibbid is supplied or when a password is present.
if ((shibbid == null) || (password != null))
return BAD_ARGS;
// Locate the eperson
EPerson eperson = null;
try
{
eperson = EPerson.findByNetid(context, shibbid);
}
catch (SQLException e)
{
}
boolean loggedIn = false;
// if they entered a shibbid that matches an eperson
if (eperson != null)
{
// shibbid corresponds to active account
if (eperson.getRequireCertificate())
return CERT_REQUIRED;
else if (!eperson.canLogIn())
return BAD_ARGS;
log.info(LogManager.getHeader(context, "authenticate", "type=ediauth"));
context.setCurrentUser(eperson);
// Check if user should be added to the JorumUKUser group
try{
context.setIgnoreAuthorization(true);
checkJorumUKUserGroup(context, shibbid, request, eperson);
}
catch (AuthorizeException e)
{
return NO_SUCH_USER;
}
finally
{
context.setIgnoreAuthorization(false);
}
return SUCCESS;
}
// the user does not already exist so create an eperson for them
else
{
// Register the new user automatically
log.info(LogManager.getHeader(context, "autoregister", "netid=" + shibbid));
if (canSelfRegister(context, request, shibbid))
{
try
{
context.setIgnoreAuthorization(true);
eperson = EPerson.create(context);
eperson.setEmail(shibbid);
// if ((ldap.ldapGivenName!=null)&&(!ldap.ldapGivenName.equals(""))) eperson.setFirstName(ldap.ldapGivenName);
// if ((ldap.ldapSurname!=null)&&(!ldap.ldapSurname.equals(""))) eperson.setLastName(ldap.ldapSurname);
eperson.setNetid(shibbid);
eperson.setCanLogIn(true);
AuthenticationManager.initEPerson(context, request, eperson);
eperson.update();
context.commit();
context.setCurrentUser(eperson);
// Check if user should be added to JorumUKUser group
checkJorumUKUserGroup(context, shibbid, request, eperson);
}
catch (AuthorizeException e)
{
return NO_SUCH_USER;
}
finally
{
context.setIgnoreAuthorization(false);
}
log.info(LogManager.getHeader(context, "authenticate", "type=ediauth-login, created ePerson"));
return SUCCESS;
}
else
{
// No auto-registration for valid certs
log.info(LogManager.getHeader(context, "failed_login", "type=ediauth-login"));
return NO_SUCH_USER;
}
}
}
private void checkJorumUKUserGroup(Context context, String shibbid,
HttpServletRequest request, EPerson eperson) throws SQLException,
AuthorizeException
{
String ea_services = request.getParameter(EA_SERVICES);
try
{
if (ea_services != null)
{
String decodedServices = URLDecoder.decode(ea_services, "UTF-8");
log.info("Decoded ea_services: " + decodedServices);
String[] services = decodedServices.split(",");
for (String service : services)
{
if (service.trim().equals(JORUMUK_USER_SERVICE))
{
// Check if already in JorumUKUser
Group jorumUKUserGroup = Group.findByName(context, JORUMUK_USER_GROUP);
if (!jorumUKUserGroup.isMember(eperson))
{
jorumUKUserGroup.addMember(eperson);
log.info("Added " + shibbid + " to JorumUKUser group");
jorumUKUserGroup.update();
break;
}
}
}
}
}
catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Nothing extra to initialize.
*/
public void initEPerson(Context context,
HttpServletRequest request,
EPerson eperson)
throws SQLException
{
}
}