/**
   * Authenticate the given username/password pair, in conjunction with the onBehalfOf user. The
   * rules are that the username/password pair must successfully authenticate the user, and the
   * onBehalfOf user must exist in the user database.
   *
   * @param context
   * @param auth
   * @return a SWORD context holding the various user information
   * @throws SwordAuthException
   * @throws SwordError
   * @throws DSpaceSwordException
   */
  private SwordContext authenticate(Context context, AuthCredentials auth)
      throws SwordAuthException, SwordError, DSpaceSwordException {
    String obo = auth.getOnBehalfOf();
    String un = auth.getUsername();
    String pw = auth.getPassword();

    // smooth out the OnBehalfOf request, so that empty strings are
    // treated as null
    if ("".equals(obo)) {
      obo = null;
    }

    // first find out if we support on-behalf-of deposit
    boolean mediated =
        ConfigurationManager.getBooleanProperty("swordv2-server", "on-behalf-of.enable");
    if (!mediated && obo != null) {
      // user is trying to do a mediated deposit on a repository which does not support it
      log.error("Attempted mediated deposit on service not configured to do so");
      throw new SwordError(
          UriRegistry.ERROR_MEDIATION_NOT_ALLOWED,
          "Mediated deposit to this service is not permitted");
    }

    log.info(
        LogManager.getHeader(
            context, "sword_authenticate", "username="******",on_behalf_of=" + obo));

    try {
      // attempt to authenticate the primary user
      SwordContext sc = new SwordContext();
      EPerson ep = null;
      boolean authenticated = false;
      if (this.authenticates(context, un, pw)) {
        // if authenticated, obtain the eperson object
        ep = context.getCurrentUser();

        if (ep != null) {
          authenticated = true;
          sc.setAuthenticated(ep);
          // Set any special groups - invoke the authentication mgr.
          int[] groupIDs = AuthenticationManager.getSpecialGroups(context, null);

          for (int i = 0; i < groupIDs.length; i++) {
            context.setSpecialGroup(groupIDs[i]);
            log.debug("Adding Special Group id=" + String.valueOf(groupIDs[i]));
          }

          sc.setAuthenticatorContext(context);
          sc.setContext(context);
        }

        // if there is an onBehalfOfuser, then find their eperson
        // record, and if it exists set it.  If not, then the
        // authentication process fails
        EPerson epObo = null;
        if (obo != null) {
          epObo = EPerson.findByEmail(context, obo);
          if (epObo == null) {
            epObo = EPerson.findByNetid(context, obo);
          }

          if (epObo != null) {
            sc.setOnBehalfOf(epObo);
            Context oboContext = this.constructContext();
            oboContext.setCurrentUser(epObo);
            // Set any special groups - invoke the authentication mgr.
            int[] groupIDs = AuthenticationManager.getSpecialGroups(oboContext, null);

            for (int i = 0; i < groupIDs.length; i++) {
              oboContext.setSpecialGroup(groupIDs[i]);
              log.debug("Adding Special Group id=" + String.valueOf(groupIDs[i]));
            }
            sc.setContext(oboContext);
          } else {
            authenticated = false;
            throw new SwordError(
                UriRegistry.ERROR_TARGET_OWNER_UNKNOWN,
                "unable to identify on-behalf-of user: "******"sword_unable_to_set_user", "username="******"Unable to authenticate with the supplied credentials");
        } else {
          // FIXME: this shouldn't ever happen now, but may as well leave it in just in case
          // there's a bug elsewhere
          log.info(
              LogManager.getHeader(
                  context,
                  "sword_unable_to_set_on_behalf_of",
                  "username="******",on_behalf_of=" + obo));
          throw new SwordAuthException("Unable to authenticate the onBehalfOf account");
        }
      }

      return sc;
    } catch (SQLException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSwordException(
          "There was a problem accessing the repository user database", e);
    } catch (AuthorizeException e) {
      log.error("caught exception: ", e);
      throw new SwordAuthException("There was a problem authenticating or authorising the user", e);
    }
  }
Example #2
0
  /**
   * Obtain a new context object. If a context object has already been created for this HTTP
   * request, it is re-used, otherwise it is created. If a user has authenticated with the system,
   * the current user of the context is set appropriately.
   *
   * @param request the HTTP request
   * @return a context object
   */
  public static Context obtainContext(HttpServletRequest request) throws SQLException {

    // Set encoding to UTF-8, if not set yet
    // This avoids problems of using the HttpServletRequest
    // in the getSpecialGroups() for an AuthenticationMethod,
    // which causes the HttpServletRequest to default to
    // non-UTF-8 encoding.
    try {
      if (request.getCharacterEncoding() == null) {
        request.setCharacterEncoding(Constants.DEFAULT_ENCODING);
      }
    } catch (Exception e) {
      log.error("Unable to set encoding to UTF-8.", e);
    }

    Context c = (Context) request.getAttribute("dspace.context");

    if (c == null) {
      // No context for this request yet
      c = new Context();
      HttpSession session = request.getSession();

      // See if a user has authentication
      Integer userID = (Integer) session.getAttribute("dspace.current.user.id");

      if (userID != null) {
        String remAddr = (String) session.getAttribute("dspace.current.remote.addr");
        if (remAddr != null && remAddr.equals(request.getRemoteAddr())) {
          EPerson e = EPerson.find(c, userID.intValue());

          Authenticate.loggedIn(c, request, e);
        } else {
          log.warn(
              "POSSIBLE HIJACKED SESSION: request from "
                  + request.getRemoteAddr()
                  + " does not match original "
                  + "session address: "
                  + remAddr
                  + ". Authentication rejected.");
        }
      }

      // Set any special groups - invoke the authentication mgr.
      int[] groupIDs = AuthenticationManager.getSpecialGroups(c, request);

      for (int i = 0; i < groupIDs.length; i++) {
        c.setSpecialGroup(groupIDs[i]);
        log.debug("Adding Special Group id=" + String.valueOf(groupIDs[i]));
      }

      // Set the session ID and IP address
      String ip = request.getRemoteAddr();
      if (useProxies == null) {
        useProxies = ConfigurationManager.getBooleanProperty("useProxies", false);
      }
      if (useProxies && request.getHeader("X-Forwarded-For") != null) {
        /* This header is a comma delimited list */
        for (String xfip : request.getHeader("X-Forwarded-For").split(",")) {
          if (!request.getHeader("X-Forwarded-For").contains(ip)) {
            ip = xfip.trim();
          }
        }
      }
      c.setExtraLogInfo("session_id=" + request.getSession().getId() + ":ip_addr=" + ip);

      // Store the context in the request
      request.setAttribute("dspace.context", c);
    }

    // Set the locale to be used
    Locale sessionLocale = getSessionLocale(request);
    Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale);
    c.setCurrentLocale(sessionLocale);

    return c;
  }