Package com.almende.eve.auth.google

Source Code of com.almende.eve.auth.google.AuthServlet

/**
* AuthServlet for Google OAuth 2.0
*
* Jos de Jong, 2013-02-15
*
* Used libraries:
*     jackson-annotations-2.0.0.jar
*     jackson-core-2.0.0.jar
*     jackson-databind-2.0.0.jar
*
* Documentation:
*     https://developers.google.com/accounts/docs/OAuth2WebServer
*/
package com.almende.eve.auth.google;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.almende.eve.config.Config;
import com.almende.eve.rpc.jsonrpc.JSONRequest;
import com.almende.eve.rpc.jsonrpc.jackson.JOM;
import com.almende.util.HttpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;


@SuppressWarnings("serial")
public class AuthServlet extends HttpServlet {
  private Logger logger = Logger.getLogger(this.getClass().getSimpleName());
 
  // Specify the correct client id and secret for web applications
  // Create them at the Google API console: https://code.google.com/apis/console/
  private String CLIENT_ID = null;
  private String CLIENT_SECRET = null;
  String REDIRECT_URI = null;
 
  // hard coded uri's
  private String AGENTS_METHOD = "setAuthorization";
  private String OAUTH_URI  = "https://accounts.google.com/o/oauth2";
  private String CONFIG_FILENAME = "/WEB-INF/eve.yaml";
  private String SPACE = " ";
  private String SCOPE =
    "https://www.googleapis.com/auth/userinfo.email" + SPACE +
    "https://www.googleapis.com/auth/userinfo.profile" + SPACE +
    "https://www.googleapis.com/auth/calendar" + SPACE +
    "https://www.googleapis.com/auth/tasks";

  private ObjectMapper mapper = new ObjectMapper();

  @Override
  public void init() {
    try {
      // load configuration
      InputStream is = getServletContext().getResourceAsStream(CONFIG_FILENAME);
      Config config = new Config(is);

      CLIENT_ID = config.get("google", "client_id");
      if (CLIENT_ID == null) {
        throw new Exception("Parameter 'google.client_id' missing in config");
      }
     
      CLIENT_SECRET = config.get("google", "client_secret");
      if (CLIENT_SECRET == null) {
        throw new Exception("Parameter 'google.client_secret' missing in config");
      }

      REDIRECT_URI = config.get("google_auth_servlet_url");
     
      // TODO: cleanup deprecated parameter some day (deprecated since 2013-02-15)
      if (REDIRECT_URI == null) {
        REDIRECT_URI = config.get("auth_google_servlet_url");
        if (REDIRECT_URI != null) {
          logger.warning("Parameter 'auth_google_servlet_url' is deprecated. " +
              "Use 'google_auth_servlet_url' instead.");
        }
      }

      if (REDIRECT_URI == null) {
        String path = "auth_google_servlet_url";
        Exception e = new Exception("Config parameter '" + path + "' is missing");
        e.printStackTrace();
      }     
    } catch (Exception e) {
      e.printStackTrace();
    }   
  }
 
  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    // read parameters code and access_token from query parameters or cookies
    String code = req.getParameter("code");
    String state = req.getParameter("state");
    String error = req.getParameter("error");
    String agentUrl = req.getParameter("agentUrl");
    String agentMethod = req.getParameter("agentMethod");
    String applicationCallback = req.getParameter("applicationCallback");

    PrintWriter out = resp.getWriter();
    resp.setContentType("text/html");

    // print error if any
    if (error != null) {
      printPageStart(out);
      printError(out, error);   
      printPageEnd(out);
      return;
    }
   
    // directly redirect to Google authorization page if an agents URL is provided
    if (agentUrl != null && agentMethod != null) {
      redirectToGoogleAuthorization(resp, agentUrl, agentMethod, applicationCallback);
      return;
    }

    // First step: show a form to authenticate
    if (code == null && state == null) {
      printPageStart(out);
      printAuthorizeForm(out);
      printPageEnd(out);
      return;
    }

    // Second step: exchange code with authentication token
    // After having authorized at google, the user is send back to this
    // servlet, with the url containing a code and status
    if (code != null && state != null){
      ObjectNode auth = exchangeCodeForAuthorization(code);

      // TODO: remove logging
      //System.out.println("Authorization code exchanged for access token: " + mapper.writeValueAsString(auth));
     
      if (auth.has("error")) {
        printPageStart(out);
        printError(out, mapper.writeValueAsString(auth.get("error")));
        printPageEnd(out);             
        return;
      }
      ObjectNode stateJson = mapper.readValue(state, ObjectNode.class);
      String statusAgentUrl = stateJson.has("agentUrl") ? stateJson.get("agentUrl").asText() : null;
      String statusAgentMethod = stateJson.has("agentMethod") ? stateJson.get("agentMethod").asText() : null;
      String statusApplicationCallback = stateJson.has("applicationCallback") ? stateJson.get("applicationCallback").asText() : null;

      // send the retrieved authorization to the agent
      sendAuthorizationToAgent(statusAgentUrl, statusAgentMethod, auth);

      if (statusApplicationCallback != null) {
        resp.sendRedirect(statusApplicationCallback);
        return;
      }
      else {
        printPageStart(out);
        printSuccess(out, statusAgentUrl);
        printPageEnd(out);
        return;
      }
    }   
  }
 
  private String createAuthorizationUrl() throws IOException {
    Map<String, String> params = new HashMap<String, String>();
    params.put("scope", SCOPE);
    params.put("redirect_uri", REDIRECT_URI);
    params.put("response_type", "code");
    params.put("access_type", "offline");
    params.put("client_id", CLIENT_ID);
    params.put("approval_prompt", "force");
    String url = HttpUtil.appendQueryParams(OAUTH_URI + "/auth", params);
   
    return url;
  }
 
  private void redirectToGoogleAuthorization(HttpServletResponse resp,
      String agentUrl, String agentMethod, String applicationCallback) throws IOException {
    String url = createAuthorizationUrl();
    ObjectNode st = JOM.createObjectNode();
    st.put("agentUrl", agentUrl);
    st.put("agentMethod", agentMethod);
    if (applicationCallback != null) {
      st.put("applicationCallback", applicationCallback);
    }

    url += "&state=" +
      URLEncoder.encode(JOM.getInstance().writeValueAsString(st), "UTF-8");
    resp.sendRedirect(url);   
  }

  private ObjectNode exchangeCodeForAuthorization(String code) throws IOException {
    Map<String, String> params = new HashMap<String, String>();
    params.put("code", code);
    params.put("client_id", CLIENT_ID);
    params.put("client_secret", CLIENT_SECRET);
    params.put("redirect_uri", REDIRECT_URI);
    params.put("grant_type", "authorization_code");
    String res = HttpUtil.postForm(OAUTH_URI + "/token", params);

    ObjectNode json = mapper.readValue(res, ObjectNode.class);
    return json;
  }
 
  private void sendAuthorizationToAgent(String agentUrl, String agentMethod,
      ObjectNode auth) throws IOException {
    JSONRequest rpcRequest = new JSONRequest(agentMethod, auth);
    HttpUtil.post(agentUrl, rpcRequest.toString());
  }
 
  private void printPageStart(PrintWriter out) {
    out.print("<html>" +
        "<head>" +
        "<title>Authorize Eve agents</title>" +
        "<style>" +
        "body {width: 700px;}" +
        "body, th, td, input {font-family: arial; font-size: 10pt; color: #4d4d4d;}" +
        "th {text-align: left;}" +
        "input[type=text] {border: 1px solid lightgray;}" +
        ".error {color: red;}" +
        "</style>" +
        "</head>" +
        "<body>" +
        "<h1>Authorize Eve agents</h1>" +
        "<p>" +
        "On this page, you can grant an Eve agent access to your data, " +
        "for example access to your calendar." +
        "</p>");   
  }
 
  private void printPageEnd(PrintWriter out) {
    out.print(
      "</body>" +
      "</html>"     
    );
  }
 
  private void printAuthorizeForm(PrintWriter out) throws IOException {
    String url = createAuthorizationUrl();
    out.print("<script type='text/javascript'>" +
      "function auth() {" +
      "  var state={" +
      "    \"agentUrl\": document.getElementById('agentUrl').value," +
      "    \"agentMethod\": document.getElementById('agentMethod').value" +
      "  };" +
      "  var url='" + url + "'+ '&state=' + encodeURI(JSON.stringify(state));" +
      "  window.location.href=url;" +
      "}" +
      "</script>" +
      "<table>" +
      "<tr><td>Agent url</td><td><input type='text' id='agentUrl' value=''" +
        " style='width: 400px;'/></td></tr>" +
        "<tr><td>Agent method</td><td><input type='text' id='agentMethod' value='" +
        AGENTS_METHOD + "' style='width: 400px;'/></td></tr>" +
      "<tr><td><button onclick='auth();'>Authorize</button></td></tr>" +
      "</table>" +
      "<script type='text/javascript'>" +
      "  document.getElementById('agentUrl').value = document.location.origin + '/agents/agentid/';" +
      "</script>"
    );   
  }
 
  private void printSuccess(PrintWriter out, String agentUrl) {
    out.print("<p>Agent is succesfully authorized.</p>");
    out.print("<p><a href=\"" + agentUrl + "\">" + agentUrl + "</a></p>");
    out.print("<button onclick='window.location.href=\"" +
          REDIRECT_URI + "\";'>Ok</button>");
  }
 
  private void printError(PrintWriter out, String error) {
    out.print("<p>An error occurred</p>");       
    out.print("<pre class='error'>" + error + "</pre>");       
    out.print("<button onclick='window.location.href=\"" +
          REDIRECT_URI + "\";'>Ok</button>");     
  }
}
TOP

Related Classes of com.almende.eve.auth.google.AuthServlet

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.