Package org.orgama.server.auth.source

Source Code of org.orgama.server.auth.source.FacebookUserServiceViaHttp

package org.orgama.server.auth.source;

import static org.orgama.server.auth.IFacebookUserService.*;

import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import org.orgama.server.Orgama;
import org.orgama.server.auth.IFacebookUserService;
import org.orgama.shared.ICookieHandler;
import org.orgama.shared.Logger;
import org.orgama.shared.auth.except.AuthException;
import org.orgama.shared.except.OrgException;

/**
* Facebook user service for use in devmode and production.  This will use the
* known oauth and facebook url patterns to get the accessToken from the code
* which is presumed to be in the url as a param. 
* @author kguthrie
*/
public class FacebookUserServiceViaHttp implements IFacebookUserService {

  public static final String APP_SECRET_ID_FILE =
      "META-INF/facebook-app-secret-id.txt";
  public static final String DEFAULT_APP_ID = "ApplicationIdPlaceHolder";
  public static final String DEFAULT_APP_SECRET_ID =
      "ApplicationSecretIdPlaceHolder";
 
  private final Provider<HttpServletRequest> requestProvider;
  private final ICookieHandler cookieHandler;
 
  private String accessTokenUrlPattern;
  private String meUrlPattern;
  private String signInUrlPattern;
  private String signOutUrlPattern;
 
  private String applicationId;
 
  private boolean initialized;
 
  @Inject
  public FacebookUserServiceViaHttp(
      Provider<HttpServletRequest> requestProvider,
      ICookieHandler cookieHander) {
    this.requestProvider = requestProvider;
    this.cookieHandler = cookieHander;
   
    applicationId = DEFAULT_APP_ID;
   
    initialized = false;
  }

  /**
   * ensures the urls used by this service are initialized
   */
  private void init() {
   
    if (initialized) {
      return;
    }
   
    initImpl();
   
    initialized = true;
  }
 
  /**
   * synchronized implementation of the initializion code
   */
  private synchronized void initImpl() {
    if (initialized) {
      return;
    }
   
    String applicationSecretId = Orgama.loadFileFromAppRoot(
        APP_SECRET_ID_FILE);
   
    if (applicationSecretId == null) {
      applicationSecretId = DEFAULT_APP_SECRET_ID;
    }
   
    //Create sign-in and sign-out url patterns based on whether this is
    //production or development.  The local mock facebook service is used
    //for development while the real facebook urls
    if (!Orgama.isProduction()) {
      accessTokenUrlPattern = String.format(
          "%s/r/facebook/access_token" +
              "?client_id=%s&redirect_uri=%%s" +
              "&client_secret=%s&code=%%s",
          Orgama.getDomain(),  applicationId, applicationSecretId);
     
      meUrlPattern = String.format("%s/r/facebook/me?access_token=%%s",
          Orgama.getDomain());
     
      signInUrlPattern = String.format(
          "../r/facebook/login?client_id=%s&" +
              "redirect_uri=%%s&state=%%s",
          applicationId);
      signOutUrlPattern = "../r/facebook/logout?next=%s&access_token=%s";
    }
    else {
      accessTokenUrlPattern = String.format(
          "https://graph.facebook.com/oauth/access_token" +
              "?client_id=%s&redirect_uri=%%s" +
              "&client_secret=%s&code=%%s",
          applicationId, applicationSecretId);
     
      meUrlPattern = "https://graph.facebook.com/me?access_token=%s";
     
      signInUrlPattern = String.format(
          "https://www.facebook.com/dialog/oauth?client_id=%s&" +
              "redirect_uri=%%s&state=%%s",
          applicationId);
     
      signOutUrlPattern =
          "https://www.facebook.com/logout.php?next=%s&access_token=%s";
    }
  }
 
  /**
   * Used to optionally inject the application id into the user service
   * @param applicationId
   */
  @Inject(optional = true)
  public void setApplicationId(@ApplictionId String applicationId) {
    this.applicationId = applicationId;
  }
 
  /**
   * Get the signInUrl for facebook
   * @return
   */
  @Override
  public String getSignInUrl(String redirectUri) {
    init();
   
    if (!redirectUri.endsWith("/")) {
      redirectUri += "/";
    }
   
    try {
      redirectUri = URLEncoder.encode(redirectUri, "UTF-8");
    }
    catch(Exception ex) {
      throw new OrgException("Error encoding redirect uri", ex);
    }
     
    return String.format(signInUrlPattern, redirectUri,
        cookieHandler.getValue("JSESSIONID"));
  }

  /**
   * Get the sign out url for facebook
   * @param accessToken
   * @return
   */
  @Override
  public String getSignOutUrl(String redirectUri, String accessToken) {
    init();
   
    if (!redirectUri.endsWith("/")) {
      redirectUri += "/";
    }
   
    try {
      redirectUri = URLEncoder.encode(redirectUri, "UTF-8");
    }
    catch(Exception ex) {
      throw new OrgException("Error encoding redirect uri", ex);
    }
     
    return String.format(signOutUrlPattern, redirectUri, accessToken);
  }

  /**
   * Get the access token by performing a url get on the configured url
   * resource for exchanging code for access token.
   * @return
   */
  @Override
  public String getAccessToken() {
   
    init();
   
    HttpServletRequest request = requestProvider.get();
    String code = request.getParameter("code");
    String state = request.getParameter("state");
   
    if (Strings.isNullOrEmpty(code)) {
      Logger.error(
          "No code parameter was found in the request url");
      return null;
    }
   
    if (Strings.isNullOrEmpty(state)
        || !state.equals(cookieHandler.getValue("JSESSIONID"))) {
      Logger.error("Mismatch in oauth state variable.  This " +
          "could be due to a XSRF attack");
      return null;
    }

    Logger.info("Making a request to facebook for accessToken");

    String redirectUri = Orgama.getDomain();

    if (!redirectUri.endsWith("/")) {
      redirectUri += "/";
    }

    try {
      redirectUri = URLEncoder.encode(redirectUri, "UTF-8");
    }
    catch(Exception ex) {
      throw new OrgException("Error encoding redirect uri", ex);
    }

    String result = Orgama.loadFromUrl(
        String.format(accessTokenUrlPattern, redirectUri, code));

    Logger.info("Request to facebook returned");

    if (Strings.isNullOrEmpty(result)) {
      Logger.error("Empty result when trying to get " +
          "access token from facebook");
      return null;
    }

    result = getStringBetween(result, "access_token=", "&");

    //No access token in response from server means user not logged in
    if (Strings.isNullOrEmpty(result)) {
      return null;
    }

    return result;
  }

 
  /**
   * Get the id of the user from the facebook person service. 
   * @param accessToken
   * @return
   */
  @Override
  public String getUserId(String accessToken) {
   
    init();
   
    Logger.info("Making a request to facebook for user id");

    String result = Orgama.loadFromUrl(
        String.format(meUrlPattern, accessToken));

    Logger.info("Request to facebook returned");

    if (Strings.isNullOrEmpty(result)) {
      Logger.error("Empty result when trying to get " +
          "access token from facebook");
      return null;
    }

    result = getStringBetween(result, "\"id\":\"", "\"");

    //No user id in response from server means user not logged in
    if (Strings.isNullOrEmpty(result)) {
      return null;
    }

    return result;
  }

   
    /**
     * returns the string between the first occurrence of the before string
     * and the first occurrence of the after string following the before string.
     * Null is returned if no instances of before are found.  If an instance
     * of before is found, but no instance of after is found, then all contents
     * following before are returned.  The same holds if after is null
     * @param toSearch
     * @param before
     * @param after
     * @return
     */
    public String getStringBetween(String toSearch,
            String before, String after) {
        int start;
        int end;
        String result;
       
        if (toSearch == null || before == null) {
            return null;
        }
       
        if ((start = toSearch.indexOf(before)) < 0) {
            return null;
        }
       
        start += before.length();
       
        if (start == toSearch.length()) {
            return "";
        }
       
        if (after == null ||
                ((end = toSearch.indexOf(after, start)) < 0)) {
            result = toSearch.substring(start);
        }
        else {
            result = toSearch.substring(start, end);
        }
       
        return result;
    }
   
}
TOP

Related Classes of org.orgama.server.auth.source.FacebookUserServiceViaHttp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.