Wednesday, August 29, 2012

OAuth2.0 Implementation for Google API in JAVA or PHP

Using OAuth2.0 authenticating your web application with Google API is very easy.  This will help your applications to maintain sing user repository from Google logging, and no need to maintain any password at your application side.  Here the idea is to give an idea of complete Web Server flow (Oauth2 web server side dance ) and understand it completely with complete open source technologies.

First step is go to Google API Console and register a project then create a Web Application  userid and secret key.  (Make sure that the registering URL will have your application's context path).
Note: Modify the userid/secretkeys as per your settings.

Create a web project ( say TestProject) and then create a servlet as shown below:


package com.test.oauth;

import java.io.BufferedReader;
import java.io.IOException;

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

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.io.IOUtils;

public class OAuthTwoCallBackServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private static String client_id = "895498929378-4uohdps8sb5v6jp8saf0rea73c0h87nr.apps.googleusercontent.com";
private static String client_secret = "LsIy_r4-S22jGwGJkbNeYQ1H";
private static String redirectURL = "http://localhost:8080/TestProject/callback";
private String auth_code = null;

public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {

System.out.println("Callback to URI that is configured in Google API Console");
resp.setContentType("text/html");
resp.getWriter().println(" OAuth2.0 example in Web Server Flow");
resp.getWriter().println(" ");
resp.getWriter().println("
");


if (req.getParameter("code") == null) {

if (req.getParameter("error") != null) {
resp.getWriter().println("Hello, " + req.getParameter("error"));
} else {

resp.getWriter().println("");
resp.getWriter().println("");
resp.getWriter().println("
"); resp.getWriter().println("");
resp.getWriter().println("

Hello

");
resp.getWriter().println("To login with Google Account click here ");
resp.getWriter().println("");
resp.getWriter().println(" resp.getWriter().println(" alt='Powered by Google App Engine' />");
resp.getWriter().println("
"); resp.getWriter().println("
"); }
} else {
resp.getWriter().println("

Code

");
resp.getWriter().println("Authentication Code = " + req.getParameter("code"));
this.auth_code = req.getParameter("code");

// Exchange the code for token
HttpClient httpclient = new HttpClient();
BufferedReader bufferedreader = null;
PostMethod postmethod = new PostMethod(
"https://accounts.google.com/o/oauth2/token");
postmethod.addParameter("code", auth_code);
postmethod.addParameter("client_id", client_id);
postmethod.addParameter("client_secret", client_secret);
postmethod.addParameter("redirect_uri", redirectURL);
postmethod.addParameter("grant_type", "authorization_code");
String access_token = null;
String token_type = null;
int expires_in = 0;
String id_token = null;
try {

int rCode = httpclient.executeMethod(postmethod);
System.out.println("HTTP POST for Token rCode is" + rCode);

if (rCode == HttpStatus.SC_NOT_IMPLEMENTED) {
System.err.println("The Post postmethod is not implemented by this URI");
postmethod.getResponseBodyAsString();
} else if (rCode == HttpStatus.SC_NOT_ACCEPTABLE) {
System.out.println(postmethod.getResponseBodyAsString());
} else {

String jsonTxt = IOUtils.toString(postmethod
.getResponseBodyAsStream());

JSONObject json = (JSONObject) JSONSerializer
.toJSON(jsonTxt);

access_token = json.getString("access_token");
token_type = json.getString("token_type");
expires_in = json.getInt("expires_in");
id_token = json.getString("id_token");
System.out.println("======== TOKEN INFO ========");
System.out.println("access_token: " + access_token);
System.out.println("token_type: " + token_type);
System.out.println("expires_in: " + expires_in);
System.out.println("id_token: " + id_token);
System.out.println("=========================");
resp.getWriter().println("

Token & Refresh

");
resp.getWriter().println("Access Token = " + access_token);
resp.getWriter().println("Refresh Token = " + id_token);
resp.getWriter().println("Expire Time (Seconds) = " + expires_in);
resp.getWriter().println("Token Type = " + token_type);
}
} catch (Exception e) {
System.err.println(e);
} finally {
postmethod.releaseConnection();
if (bufferedreader != null)
try {
bufferedreader.close();
} catch (Exception fe) {
fe.printStackTrace();
}
}

//Calling Google account info API
User user = null;
httpclient = new HttpClient();
bufferedreader = null;
GetMethod getmethod = new GetMethod("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + access_token);
try {
int rCode = httpclient.executeMethod(getmethod);
System.out.println("HTTP GET for User rCode is" + rCode);

if (rCode == HttpStatus.SC_NOT_IMPLEMENTED) {
System.err
.println("The Get method is not implemented by this URI");
getmethod.getResponseBodyAsString();
} else if (rCode == HttpStatus.SC_NOT_ACCEPTABLE) {
System.out.println(getmethod.getResponseBodyAsString());
} else {

String jsonTxt = IOUtils.toString(getmethod
.getResponseBodyAsStream());
JSONObject json = (JSONObject) JSONSerializer
.toJSON(jsonTxt);

user = new User();
user.id = json.getString("id");
user.name = json.getString("name");
user.email = json.getString("email");
user.picture = json.getString("picture");
user.gender = json.getString("gender");
user.locale = json.getString("locale");

System.out.println("============ TOKEN INFO ===============");
System.out.println("id: " + user.id);
System.out.println("name: " + user.name);
System.out.println("Gender: " + user.gender);
System.out.println("email: " + user.email);
System.out.println("pictureURL: " + user.picture);
System.out.println("Locale: " + user.locale);
System.out.println("====================================");
}
} catch (Exception e) {
System.err.println(e);
} finally {
postmethod.releaseConnection();
if (bufferedreader != null)
try {
bufferedreader.close();
} catch (Exception fe) {
fe.printStackTrace();
}
}

// Get User Information
//resp.setContentType("text/html");
resp.getWriter().println("

User Information

");
resp.getWriter().println("
");
Property  Data

resp.getWriter().println("
Id
" + user.getId()+ "
");
resp.getWriter().println("
Name
" + user.getName()+ "
");
resp.getWriter().println("
Email
" + user.getEmail()+ "
");
resp.getWriter().println("
Gender
" + user.getGender()+ "
");
resp.getWriter().println("
Image

");
resp.getWriter().println("
Locale
" + user.getLocale()+ "
");
resp.getWriter().println("
");
}
}

public class User {
public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPicture() {
return picture;
}

public void setPicture(String picture) {
this.picture = picture;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public String getLocale() {
return locale;
}

public void setLocale(String locale) {
this.locale = locale;
}

String id;
String email;
String name;
String picture;
String gender;
String locale;

@Override
public String toString() {
return String.format("id:%s,name:%s,email:%s,gender:%d,locale:%s",
id, name, email, gender, locale);
}
}

public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
System.out.println("This is never called");
}
}

The web.xml file should have the following as well.

  TestProject
  
    
ServletName: OAuth2Callback
Servlet calssname: com.test.oauth.OAuthTwoCallBackServlet
Servlet Mapping: OAuth2Callback
Servlet Mapping Name /callback
     

Similarly for PHP I have create a Test project and Home.php file nothing else is required.
The Home.php :




OAuth2.0 Implementatin in PHP by Khaleel



if(!isset($_GET["code"]) || $_GET["code"] ==""){

?>

 Please click on Login button to lonon Google Apps using OAuth2.0 and get the Google Aaacount Details














}else{

$userProfile = array(
'id' => '',
'name' => '',
'gender' => '',
'email' => '',
'picture' => '',
'locale' => ''
);

$userProfile = authValidateUser($_GET["code"]);

if(isset($userProfile["email"]) && $userProfile["email"] != ""){
?>
User Property Data

Name    
Email  
Gender
ID      
Picture
Locale  



}else{

?>

Unable to get User Data, Please try Again !!!




}

}


function authValidateUser($code)
{
$OAuth = array(
'oauth_uri' => 'https://accounts.google.com/o/oauth2/auth',
'client_id' => '284443344502-do31sm7eo7nogdcn5m0dmlgb0841r8j2.apps.googleusercontent.com',
'client_secret' => 'abUpKB-rqoBOx0DJv2fhJ44S',
'redirect_uri' => 'http://localhost/Test/Home.php',
'oauth_token_uri' => 'https://accounts.google.com/o/oauth2/token'
);

$token = array(
'access_token' => '',
'token_type' => '',
'expires_in' => '',
'refresh_token' => ''
);

$userinfo = array(
'id' => '',
'name' => '',
'gender' => '',
'email' => '',
'picture' => '',
'locale' => ''
);


if(isset($code) && $code != ""){

// now exchange Authorization code for access token and refresh token
$token_response = _get_auth_token($OAuth, $code);
$json_obj = json_decode($token_response);
$token["access_token"] = $json_obj->access_token;
$token["token_type"] = $json_obj->token_type;
$token["expires_in"] = $json_obj->expires_in;
$token["refresh_token"] = $json_obj->refresh_token;
}

if(isset($token["access_token"]) && $token["access_token"] != ""){
//Exchange Authorization code for access token and refresh token
$userinfo_response = _get_user_info($token["access_token"]);
$json_obj = json_decode($userinfo_response);
$userinfo["id"] = $json_obj->id;
$userinfo["name"] = $json_obj->name;
$userinfo["gender"] = $json_obj->gender;
$userinfo["email"] = $json_obj->email;
$userinfo["picture"] = $json_obj->picture;
$userinfo["locale"] = $json_obj->locale;
}

return $userinfo;
}

function _get_auth_token($params, $code)
{
$url = $params['oauth_token_uri'];

$fields = array(
'code' => $code,
'client_id' => $params['client_id'],
'client_secret' => $params['client_secret'],
'redirect_uri' => $params['redirect_uri'],
'grant_type' => 'authorization_code'
);

$response = _do_post($url, $fields);
return $response;
}

function _get_refresh_token($params, $code)
{
$url = $params['oauth_token_uri'];

$fields = array(
'code' => $code,
'client_id' => $params['client_id'],
'client_secret' => $params['client_secret'],
'refresh_token' => $token['refresh_token'],
'grant_type' => 'refresh_token'
);

$response = _do_post($url, $fields);
return $response;
}

function _do_post($url, $fields)
{
$fields_string = "";

foreach ($fields as $key => $value)
{
$fields_string .= $key . "=" . $value . "&";
}
$fields_string = rtrim($fields_string, "&");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$response = curl_exec($ch);
curl_close($ch);

return $response;
}


function _get_user_info($AuthToken){
$url = "https://www.googleapis.com/oauth2/v1/userinfo";
$fields = array('access_token' => $AuthToken );
$response = _do_get($url, $fields);

//$response = logoutOauthTwoUser($AuthToken);
return $response;
}

function _do_get($url, $fields)
{
$fields_string = "";

foreach ($fields as $key => $value)
{
$fields_string .= $key . "=" . $value . "&";
}
$fields_string = rtrim($fields_string, "&");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url."?".$fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$response = curl_exec($ch);
curl_close($ch);

return $response;
}

?>
               






                        -- END ---