Class ShibAuthentication

  • All Implemented Interfaces:
    AuthenticationMethod

    public class ShibAuthentication
    extends Object
    implements AuthenticationMethod
    Shibboleth authentication for DSpace Shibboleth is a distributed authentication system for securely authenticating users and passing attributes about the user from one or more identity providers. In the Shibboleth terminology DSpace is a Service Provider which receives authentication information and then based upon that provides a service to the user. With Shibboleth DSpace will require that you use Apache installed with the mod_shib module acting as a proxy for all HTTP requests for your servlet container (typically Tomcat). DSpace will receive authentication information from the mod_shib module through HTTP headers. See for more information on installing and configuring a Shibboleth Service Provider: https://wiki.shibboleth.net/confluence/display/SHIB2/Installation See the DSpace.cfg or DSpace manual for information on how to configure this authentication module.
    Author:
    Bruc Liong, MELCOE, Xiang Kevin Li, MELCOE, Scott Phillips
    • Constructor Detail

      • ShibAuthentication

        public ShibAuthentication()
    • Method Detail

      • authenticate

        public int authenticate​(Context context,
                                String username,
                                String password,
                                String realm,
                                javax.servlet.http.HttpServletRequest request)
                         throws SQLException
        Authenticate the given or implicit credentials. This is the heart of the authentication method: test the credentials for authenticity, and if accepted, attempt to match (or optionally, create) an EPerson. If an EPerson is found it is set in the Context that was passed. DSpace supports authentication using NetID, or email address. A user's NetID is a unique identifier from the IdP that identifies a particular user. The NetID can be of almost any form such as a unique integer, string, or with Shibboleth 2.0 you can use "targeted ids". You will need to coordinate with your Shibboleth federation or identity provider. There are three ways to supply identity information to DSpace: 1) NetID from Shibboleth Header (best) The NetID-based method is superior because users may change their email address with the identity provider. When this happens DSpace will not be able to associate their new address with their old account. 2) Email address from Shibboleth Header (okay) In the case where a NetID header is not available or not found DSpace will fall back to identifying a user based-upon their email address. 3) Tomcat's Remote User (worst) In the event that neither Shibboleth headers are found then as a last resort DSpace will look at Tomcat's remote user field. This is the least attractive option because Tomcat has no way to supply additional attributes about a user. Because of this the autoregister option is not supported if this method is used. Identity Scheme Migration Strategies: If you are currently using Email based authentication (either 1 or 2) and want to upgrade to NetID based authentication then there is an easy path. Simply enable Shibboleth to pass the NetID attribute and set the netid-header below to the correct value. When a user attempts to log in to DSpace first DSpace will look for an EPerson with the passed NetID, however when this fails DSpace will fall back to email based authentication. Then DSpace will update the user's EPerson account record to set their netid so all future authentications for this user will be based upon netid. One thing to note is that DSpace will prevent an account from switching NetIDs. If an account already has a NetID set and then they try and authenticate with a different NetID the authentication will fail.
        Specified by:
        authenticate in interface AuthenticationMethod
        Parameters:
        context - DSpace context, will be modified (ePerson set) upon success.
        username - Username (or email address) when method is explicit. Use null for implicit method.
        password - Password for explicit auth, or null for implicit method.
        realm - Not used by Shibboleth-based authentication
        request - The HTTP request that started this operation, or null if not applicable.
        Returns:
        One of: SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS

        Meaning:
        SUCCESS - authenticated OK.
        BAD_CREDENTIALS - user exists, but credentials (e.g. passwd) don't match
        CERT_REQUIRED - not allowed to login this way without X.509 cert.
        NO_SUCH_USER - user not found using this method.
        BAD_ARGS - user/pw not appropriate for this method

        Throws:
        SQLException - if database error
      • getSpecialGroups

        public List<Group> getSpecialGroups​(Context context,
                                            javax.servlet.http.HttpServletRequest request)
        Get list of extra groups that user implicitly belongs to. Note that this method will be invoked regardless of the authentication status of the user (logged-in or not) e.g. a group that depends on the client network-address. DSpace is able to place users into pre-defined groups based upon values received from Shibboleth. Using this option you can place all faculty members into a DSpace group when the correct affiliation's attribute is provided. When DSpace does this they are considered 'special groups', these are really groups but the user's membership within these groups is not recorded in the database. Each time a user authenticates they are automatically placed within the pre-defined DSpace group, so if the user loses their affiliation then the next time they login they will no longer be in the group. Depending upon the shibboleth attributed use in the role-header, it may be scoped. Scoped is shibboleth terminology for identifying where an attribute originated from. For example a students affiliation may be encoded as "student@tamu.edu". The part after the @ sign is the scope, and the preceding value is the value. You may use the whole value or only the value or scope. Using this you could generate a role for students and one institution different than students at another institution. Or if you turn on ignore-scope you could ignore the institution and place all students into one group. The values extracted (a user may have multiple roles) will be used to look up which groups to place the user into. The groups are defined as authentication.shib.role.<role-name> which is a comma separated list of DSpace groups.
        Specified by:
        getSpecialGroups in interface AuthenticationMethod
        Parameters:
        context - A valid DSpace context.
        request - The request that started this operation, or null if not applicable.
        Returns:
        array of EPerson-group IDs, possibly 0-length, but never null.
      • allowSetPassword

        public boolean allowSetPassword​(Context context,
                                        javax.servlet.http.HttpServletRequest request,
                                        String email)
                                 throws SQLException
        Indicate whether or not a particular self-registering user can set themselves a password in the profile info form.
        Specified by:
        allowSetPassword in interface AuthenticationMethod
        Parameters:
        context - DSpace context
        request - HTTP request, in case anything in that is used to decide
        email - e-mail address of user attempting to register
        Returns:
        true if this method allows user to change ePerson password.
        Throws:
        SQLException - if database error
      • isImplicit

        public boolean isImplicit()
        Predicate, is this an implicit authentication method. An implicit method gets credentials from the environment (such as an HTTP request or even Java system properties) rather than the explicit username and password. For example, a method that reads the X.509 certificates in an HTTPS request is implicit.
        Specified by:
        isImplicit in interface AuthenticationMethod
        Returns:
        true if this method uses implicit authentication.
      • canSelfRegister

        public boolean canSelfRegister​(Context context,
                                       javax.servlet.http.HttpServletRequest request,
                                       String username)
                                throws SQLException
        Indicate whether or not a particular user can self-register, based on e-mail address.
        Specified by:
        canSelfRegister in interface AuthenticationMethod
        Parameters:
        context - DSpace context
        request - HTTP request, in case anything in that is used to decide
        username - e-mail address of user attempting to register
        Returns:
        true if new ePerson should be created.
        Throws:
        SQLException - if database error
      • initEPerson

        public void initEPerson​(Context context,
                                javax.servlet.http.HttpServletRequest request,
                                EPerson eperson)
                         throws SQLException
        Initialize a new e-person record for a self-registered new user.
        Specified by:
        initEPerson in interface AuthenticationMethod
        Parameters:
        context - DSpace context
        request - HTTP request, in case it's needed
        eperson - newly created EPerson record - email + information from the registration form will have been filled out.
        Throws:
        SQLException - if database error
      • loginPageURL

        public String loginPageURL​(Context context,
                                   javax.servlet.http.HttpServletRequest request,
                                   javax.servlet.http.HttpServletResponse response)
        Get login page to which to redirect. Returns URL (as string) to which to redirect to obtain credentials (either password prompt or e.g. HTTPS port for client cert.); null means no redirect.

        For Shibboleth, this URL looks like (note 'target' param is URL encoded, but shown as unencoded in this example) [shibURL]?target=[dspace.server.url]/api/authn/shibboleth?redirectUrl=[dspace.ui.url]

        This URL is used by the client to redirect directly to Shibboleth for authentication. The "target" param is then the location (in REST API) where Shibboleth redirects back to. The "redirectUrl" is the path/URL in the client (e.g. Angular UI) which the REST API redirects the user to (after capturing/storing any auth info from Shibboleth).

        Specified by:
        loginPageURL in interface AuthenticationMethod
        Parameters:
        context - DSpace context, will be modified (ePerson set) upon success.
        request - The HTTP request that started this operation, or null if not applicable.
        response - The HTTP response from the servlet method.
        Returns:
        fully-qualified URL or null
      • isEnabled

        public static boolean isEnabled()
        Check if Shibboleth plugin is enabled
        Returns:
        true if enabled, false otherwise
      • findEPerson

        protected EPerson findEPerson​(Context context,
                                      javax.servlet.http.HttpServletRequest request)
                               throws SQLException,
                                      AuthorizeException
        Identify an existing EPerson based upon the shibboleth attributes provided on the request object. There are three cases where this can occurr, each as a fallback for the previous method. 1) NetID from Shibboleth Header (best) The NetID-based method is superior because users may change their email address with the identity provider. When this happens DSpace will not be able to associate their new address with their old account. 2) Email address from Shibboleth Header (okay) In the case where a NetID header is not available or not found DSpace will fall back to identifying a user based upon their email address. 3) Tomcat's Remote User (worst) In the event that neither Shibboleth headers are found then as a last resort DSpace will look at Tomcat's remote user field. This is the least attractive option because Tomcat has no way to supply additional attributes about a user. Because of this the autoregister option is not supported if this method is used. If successful then the identified EPerson will be returned, otherwise null.
        Parameters:
        context - The DSpace database context
        request - The current HTTP Request
        Returns:
        The EPerson identified or null.
        Throws:
        SQLException - if database error
        AuthorizeException - if authorization error
      • registerNewEPerson

        protected EPerson registerNewEPerson​(Context context,
                                             javax.servlet.http.HttpServletRequest request)
                                      throws SQLException,
                                             AuthorizeException
        Register a new eperson object. This method is called when no existing user was found for the NetID or Email and autoregister is enabled. When these conditions are met this method will create a new eperson object. In order to create a new eperson object there is a minimal set of metadata required: Email, First Name, and Last Name. If we don't have access to these three pieces of information then we will be unable to create a new eperson object, such as the case when Tomcat's Remote User field is used to identify a particular user. Note, that this method only adds the minimal metadata. Any additional metadata will need to be added by the updateEPerson method.
        Parameters:
        context - The current DSpace database context
        request - The current HTTP Request
        Returns:
        A new eperson object or null if unable to create a new eperson.
        Throws:
        SQLException - if database error
        AuthorizeException - if authorization error
      • updateEPerson

        protected void updateEPerson​(Context context,
                                     javax.servlet.http.HttpServletRequest request,
                                     EPerson eperson)
                              throws SQLException,
                                     AuthorizeException
        After we successfully authenticated a user, this method will update the user's attributes. The user's email, name, or other attribute may have been changed since the last time they logged into DSpace. This method will update the database with their most recent information. This method handles the basic DSpace metadata (email, first name, last name) along with additional metadata set using the setMetadata() methods on the eperson object. The additional metadata are defined by a mapping created in the dspace.cfg.
        Parameters:
        context - The current DSpace database context
        request - The current HTTP Request
        eperson - The eperson object to update.
        Throws:
        SQLException - if database error
        AuthorizeException - if authorization error
      • swordCompatibility

        protected int swordCompatibility​(Context context,
                                         String username,
                                         String password,
                                         javax.servlet.http.HttpServletRequest request)
                                  throws SQLException
        Provide password-based authentication to enable sword compatibility. Sword compatibility will allow this authentication method to work when using sword. Sword relies on username and password based authentication and is entirely incapable of supporting shibboleth. This option allows you to authenticate username and passwords for sword sessions without adding another authentication method onto the stack. You will need to ensure that a user has a password. One way to do that is to create the user via the create-administrator command line command and then edit their permissions.
        Parameters:
        context - The DSpace database context
        username - The username
        password - The password
        request - The HTTP Request
        Returns:
        A valid DSpace Authentication Method status code.
        Throws:
        SQLException - if database error
      • initialize

        protected void initialize​(Context context)
                           throws SQLException
        Initialize Shibboleth Authentication. During initalization the mapping of additional eperson metadata will be loaded from the DSpace.cfg and cached. While loading the metadata mapping this method will check the EPerson object to see if it supports the metadata field. If the field is not supported and autocreate is turned on then the field will be automatically created. It is safe to call this methods multiple times.
        Parameters:
        context - context
        Throws:
        SQLException - if database error
      • checkIfEpersonMetadataFieldExists

        protected boolean checkIfEpersonMetadataFieldExists​(Context context,
                                                            String metadataName)
                                                     throws SQLException
        Check if a MetadataField for an eperson is available.
        Parameters:
        metadataName - The name of the metadata field.
        context - context
        Returns:
        True if a valid metadata field, otherwise false.
        Throws:
        SQLException - if database error
      • autoCreateEpersonMetadataField

        protected boolean autoCreateEpersonMetadataField​(Context context,
                                                         String metadataName)
                                                  throws SQLException
        Automatically create a new metadataField for an eperson
        Parameters:
        context - context
        metadataName - The name of the new metadata field.
        Returns:
        True if successful, otherwise false.
        Throws:
        SQLException - if database error
      • findAttribute

        protected String findAttribute​(javax.servlet.http.HttpServletRequest request,
                                       String name)
        Find a particular Shibboleth header value and return the all values. The header name uses a bit of fuzzy logic, so it will first try case sensitive, then it will try lowercase, and finally it will try uppercase. This method will not interpret the header value in any way. This method will return null if value is empty.
        Parameters:
        request - The HTTP request to look for values in.
        name - The name of the attribute or header
        Returns:
        The value of the attribute or header requested, or null if none found.
      • findSingleAttribute

        protected String findSingleAttribute​(javax.servlet.http.HttpServletRequest request,
                                             String name)
        Find a particular Shibboleth header value and return the first value. The header name uses a bit of fuzzy logic, so it will first try case sensitive, then it will try lowercase, and finally it will try uppercase. Shibboleth attributes may contain multiple values separated by a semicolon. This method will return the first value in the attribute. If you need multiple values use findMultipleAttributes instead. If no attribute is found then null is returned.
        Parameters:
        request - The HTTP request to look for headers values on.
        name - The name of the header
        Returns:
        The value of the header requested, or null if none found.
      • findMultipleAttributes

        protected List<String> findMultipleAttributes​(javax.servlet.http.HttpServletRequest request,
                                                      String name)
        Find a particular Shibboleth hattributeeader value and return the values. The attribute name uses a bit of fuzzy logic, so it will first try case sensitive, then it will try lowercase, and finally it will try uppercase. Shibboleth attributes may contain multiple values separated by a semicolon and semicolons are escaped with a backslash. This method will split all the attributes into a list and unescape semicolons. If no attributes are found then null is returned.
        Parameters:
        request - The HTTP request to look for headers values on.
        name - The name of the attribute
        Returns:
        The list of values found, or null if none found.
      • isUsed

        public boolean isUsed​(Context context,
                              javax.servlet.http.HttpServletRequest request)
        Description copied from interface: AuthenticationMethod
        Get whether the authentication method is being used.
        Specified by:
        isUsed in interface AuthenticationMethod
        Parameters:
        context - The DSpace context
        request - The current request
        Returns:
        whether the authentication method is being used.
      • canChangePassword

        public boolean canChangePassword​(Context context,
                                         EPerson ePerson,
                                         String currentPassword)
        Description copied from interface: AuthenticationMethod
        Check if the given current password is valid to change the password of the given ePerson
        Specified by:
        canChangePassword in interface AuthenticationMethod
        Parameters:
        context - The DSpace context
        ePerson - the ePerson related to the password change
        currentPassword - The current password to check
        Returns:
        true if the provided password matches with current password