org.dspace.authenticate.OpenAMAuthentication.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.authenticate.OpenAMAuthentication.java

Source

/**
 * 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
 * <p>
 * http://www.dspace.org/license/
 */
package org.dspace.authenticate;

import be.milieuinfo.security.openam.api.*;
import be.milieuinfo.security.openam.oauth.*;
import com.atmire.authenticate.*;
import com.atmire.eperson.acl.service.*;
import com.sun.jersey.api.client.*;

import java.net.*;
import java.sql.*;
import java.util.*;
import javax.servlet.http.*;
import javax.ws.rs.core.*;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.*;
import org.apache.log4j.*;
import org.dspace.authorize.*;
import org.dspace.core.*;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.*;
import org.dspace.utils.*;

public abstract class OpenAMAuthentication implements AuthenticationMethod {

    private static Logger log = Logger.getLogger(OpenAMAuthentication.class);

    public final static String SPECIAL_GROUP_REQUEST_ATTRIBUTE = "openam.specialgroup";
    private static final String ADMINISTRATOR_GROUP = "Administrator";
    private String dSpaceAdminRole;
    private String dSpaceRolePrefix;

    private EPersonAclMetadataService ePersonAclMetadataService = new DSpace().getServiceManager()
            .getServicesByType(EPersonAclMetadataService.class).get(0);

    protected DSpaceJerseyBasedOAuthIdentityService openAMIdentityService;

    protected OpenAMAuthentication() {
        final String openamServerUrl = ConfigurationManager.getProperty("authentication-openam",
                "openam.server.url");
        final String consumerToken = ConfigurationManager.getProperty("authentication-openam",
                "openam.consumer.token");
        final String consumerSecret = ConfigurationManager.getProperty("authentication-openam",
                "openam.consumer.secret");
        dSpaceRolePrefix = ConfigurationManager.getProperty("authentication-openam", "openam.role.prefix");
        dSpaceAdminRole = ConfigurationManager.getProperty("authentication-openam", "openam.admin.role");

        this.openAMIdentityService = new DSpaceJerseyBasedOAuthIdentityService();
        this.openAMIdentityService.setUrl(openamServerUrl);
        this.openAMIdentityService.setConsumerToken(new OAuthTokenPair(consumerToken, consumerSecret));
    }

    public int authenticateOpenAM(Context context, HttpServletRequest request, String ssoId) throws SQLException {
        if (!StringUtils.isBlank(ssoId)) {
            final OpenAMUserdetails userDetails = this.openAMIdentityService.getUserDetails(ssoId);
            if (userDetails != null) {

                final String userName = userDetails.getUsername();

                final String email = userDetails.getAttributeValue("mail") == null ? userName
                        : userDetails.getAttributeValue("mail");
                final String sn = userDetails.getAttributeValue("sn") == null ? userName
                        : userDetails.getAttributeValue("sn");
                final String givenName = userDetails.getAttributeValue("givenName") == null ? userName
                        : userDetails.getAttributeValue("givenName");

                if (log.isDebugEnabled()) {
                    logOpenAmUserDetails(email, userDetails);
                }

                final Collection<String> roles = userDetails.getRoles();
                if (!StringUtils.isBlank(email)) {
                    try {
                        loadGroups(context, roles, request, email);
                        final EPerson knownEPerson = EPerson.findByEmail(context, email);
                        if (knownEPerson == null) {
                            // TEMPORARILY turn off authorisation
                            context.turnOffAuthorisationSystem();
                            final EPerson eperson = createEPerson(context, request, email, sn, givenName);
                            eperson.update();
                            updateEpersonAclMetadata(context, eperson, userDetails);
                            context.commit();
                            context.restoreAuthSystemState();
                            context.setCurrentUser(eperson);

                            log.info(LogManager.getHeader(context, "login", "type=openam-interactive"));
                            return SUCCESS;
                        } else {
                            updateEpersonAclMetadata(context, knownEPerson, userDetails);
                            context.setCurrentUser(knownEPerson);
                            return SUCCESS;
                        }
                    } catch (AuthorizeException e) {
                        log.warn(LogManager.getHeader(context, "authorize_exception", ""), e);
                        return BAD_ARGS;
                    }
                } else {
                    return BAD_ARGS;
                }
            } else {
                return NO_SUCH_USER;
            }
        } else {
            return NO_SUCH_USER;
        }
    }

    private void logOpenAmUserDetails(final String email, final OpenAMUserdetails userDetails) {
        Map<String, String[]> attributes = userDetails.getAttributes();

        for (String key : attributes.keySet()) {
            logDebugForUser(email, key + " " + Arrays.asList(attributes.get(key)).toString());
        }
        logDebugForUser(email, "getOrganisatieCode [" + userDetails.getOrganisatieCode() + "]");
        logDebugForUser(email, "getOrganisatieCodeDetail [" + userDetails.getOrganisatieCodeDetail() + "]");
        logDebugForUser(email, "getPersonId [" + userDetails.getPersonId() + "]");
        logDebugForUser(email, "getUsername [" + userDetails.getUsername() + "]");
        logDebugForUser(email, "getAuthLevel [" + userDetails.getAuthLevel() + "]");

        Collection<String> roles = userDetails.getRoles();
        for (String role : roles) {
            logDebugForUser(email, "Role [" + role + "]");
        }
    }

    private void logDebugForUser(final String email, final String s) {
        log.debug("(User " + email + ") " + s);
    }

    private void updateEpersonAclMetadata(Context context, EPerson eperson, OpenAMUserdetails userDetails) {
        try {
            ePersonAclMetadataService.removeAllFields(context, eperson);

            List<OpenAMEpersonMetadataMapper> openAMEpersonMetadataMappers = new DSpace().getServiceManager()
                    .getServicesByType(OpenAMEpersonMetadataMapper.class);

            for (OpenAMEpersonMetadataMapper openAMEpersonMetadataMapper : openAMEpersonMetadataMappers) {
                openAMEpersonMetadataMapper.mapToMetadata(context, eperson, userDetails);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    protected EPerson createEPerson(Context context, HttpServletRequest request, String email, String sn,
            String givenName) throws SQLException, AuthorizeException {
        final EPerson eperson = EPerson.create(context);
        eperson.setFirstName(sn);
        eperson.setLastName(givenName);
        eperson.setEmail(email);
        eperson.setRequireCertificate(false);
        eperson.setSelfRegistered(true);
        eperson.setCanLogIn(true);
        AuthenticationManager.initEPerson(context, request, eperson);
        return eperson;
    }

    protected void loadGroups(Context context, Collection<String> roles, HttpServletRequest request, String email)
            throws SQLException, AuthorizeException {

        ArrayList<Integer> currentGroups = new ArrayList<>();

        log.info("Number of OpenAM roles received for user " + email + " is " + CollectionUtils.size(roles));

        for (String role : roles) {
            log.info("User " + email + " has OpenAM role " + role);

            if (dSpaceAdminRole.equals(role)) {
                final Group admins = Group.findByName(context, ADMINISTRATOR_GROUP);

                if (admins != null) {
                    currentGroups.add(admins.getID());

                    if (log.isDebugEnabled()) {
                        log.debug("User " + email + " was added to the " + admins.getName() + " group");
                    }

                } else {
                    log.warn(LogManager.getHeader(context, "login",
                            "Could not add user as administrator (group not found)!"));
                }
            } else if (role.startsWith(dSpaceRolePrefix)) {
                final String groupName = role.replaceAll(dSpaceRolePrefix, "");
                final Group group = Group.findByName(context, groupName);
                if (group != null) {
                    currentGroups.add(group.getID());
                    if (log.isDebugEnabled()) {
                        log.debug("User " + email + " was added to the " + group.getName() + " group");
                    }
                } else {
                    log.warn(LogManager.getHeader(context, "login",
                            "Could not add user to group:" + groupName + " (group not found)!"));
                }
            }
        }

        if (CollectionUtils.isNotEmpty(currentGroups)) {
            int[] groupIdArray = ArrayUtils.toPrimitive(currentGroups.toArray(new Integer[currentGroups.size()]));
            request.getSession().setAttribute(SPECIAL_GROUP_REQUEST_ATTRIBUTE, groupIdArray);
        }
    }

    protected class DSpaceJerseyBasedOAuthIdentityService extends JerseyBasedOAuthIdentityService {

        private static final String LOGIN_URL = BASE_PATH + "/login";

        protected URI loginUrl;

        public String login(String username, String password) {
            String token = null;

            if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
                ClientRequest clientRequest = ClientRequest.create()
                        .build(UriBuilder.fromUri(this.loginUrl).queryParam(USERNAME_QUERY_PARAM, username)
                                .queryParam(PASSWORD_QUERY_PARAM, password).build(), DEFAULT_METHOD);
                ClientResponse clientResponse = getClientResponse(clientRequest, getOAuthParameters(""),
                        getOAuth2LeggedSecrets());
                if (clientResponse.getStatus() == HttpServletResponse.SC_OK) {
                    token = getTokenId(clientResponse);
                }
            }

            return token;
        }

        public void setUrl(String serverUrl) {
            super.setServerUrl(serverUrl);
            try {
                this.loginUrl = new URI(serverUrl + LOGIN_URL);
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }

    @Override
    public int[] getSpecialGroups(Context context, HttpServletRequest request) throws SQLException {
        if (request != null && request.getSession() != null) {
            int[] groupIds = (int[]) request.getSession().getAttribute(SPECIAL_GROUP_REQUEST_ATTRIBUTE);

            if (ArrayUtils.isNotEmpty(groupIds)) {
                return groupIds;
            }
        }

        return new int[0];
    }

}