Sunday, June 22, 2014

OAuth 2.0 in Android part - 1

What is OAuth?

OAuth is an open standard for authorization. OAuth provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner, or end-user. The client then uses the access token to access the protected resources hosted by the resource server. OAuth is commonly used as a way for web surfers to log into third party web sites using their Google, Facebook or Twitter accounts, without worrying about their access credentials being compromised.



There are basically two ways to attain this (using Google service provider)

General OAuth 2.0 workflow


  •  You : the user
  • My application : the consumer
  •  Google : the provider

 When an application wants to access your data using OAuth, it needs to participate in the OAuth workflow. In order to accomplish this flow,  a series of request / responses between the consumer (my application), and the provider (Google) need to be initiated. Each interaction (consumer sending a request and provider sending a response) involves sending / receiving a set of parameters.

We’ll cover the OAuth flow in detail here, including all the steps that both the consumer, provider and user needs to take. The detailed steps are outlined here :
  The consumer registers his domain with the provider (prerequisite).
  The provider accepts the registration and provides a consumer key and a consumer secret.
  The consumer requests a request token (OAuthGetRequestToken).
  The service provider sends the request token.
  The consumer sends his request token for authorization (OAuthAuthorizeToken)
  If the user is not logged into the service provider, he does so now.
  User is authenticated by the provider. The consumer doesn’t capture the username/password
  The provider informs the user that the consumer wants to access his protected resource
  The users needs grants access to the consumer
  The provider then sends an authorized token to the consumer.
  The consumer sends his authorized token (OAuthGetAccessToken)
The service provider knows that the user has granted access and sends an access token

All of these interactions are done through HTTP requests. The provider provides the endpoints for each interaction in the OAuth flow. The consumer takes note of each endpoints, and uses them in the interaction with the provider to finish the OAuth workflow.
Most google services define the following oAuth endpoints :
OAuth Endpoint
URL
Request token endpoint
https://www.google.com/accounts/OAuthGetRequestToken
Authorization endpoint
https://www.google.com/accounts/OAuthAuthorizeToken
Access token endpoint
https://www.google.com/accounts/OAuthGetAccessToken

The consumer will send a request to each of these endpoints. The provider then responds to these requests by sending an appropriate response so that the consumer can continue

In this part will explain OAuth 2.0 using signpost lib

This process  directly takes to google login page and then grant access page and returns back to application with access_token and secret_token. Below is the flowchart to explain the process in pictorial way to get a better idea.


Below are the libraries that would be required

First we need to get the access token, lets create a generic class which will hold all the generic data like scope, url etc..

Add these constants.
public static final String CONSUMER_KEY  = "anonymous";
public static final String CONSUMER_SECRET  = "anonymous";

public static final String SCOPE  = "https://www.google.com/m8/feeds/";
public static final String REQUEST_URL  = "https://www.google.com/accounts/OAuthGetRequestToken";
public static final String ACCESS_URL  = "https://www.google.com/accounts/OAuthGetAccessToken";  
public static final String AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken";
 
public static final String GET_CONTACTS_FROM_GOOGLE_REQUEST = "https://www.google.com/m8/feeds/contacts/default/full?alt=json";
 
public static final String ENCODING  = "UTF-8";
 
public static final String OAUTH_CALLBACK_SCHEME = "oauth-example";
public static final String OAUTH_CALLBACK_HOST = "callback";
public static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;
public static final String APP_NAME             = "OAuthExample";


Now initialize consumer and provider and make a request to get token.
try {
    consumer = new CommonsHttpOAuthConsumer(C.CONSUMER_KEY, C.CONSUMER_SECRET);
    provider = new CommonsHttpOAuthProvider(C.REQUEST_URL  + "?scope=" + URLEncoder.encode                              (C.SCOPE, C.ENCODING) + "&xoauth_displayname=" + C.APP_NAME,
              C.ACCESS_URL,
              C.AUTHORIZE_URL);
     } catch (Exception e) {
      Log.e(C.TAG, "Error creating consumer / provider",e);
     }
try {
 String url = provider.retrieveRequestToken(consumer, C.OAUTH_CALLBACK_URL);
 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
 this.startActivity(intent);
   
    } catch (Exception e) {
   Log.e(C.TAG, "Error retrieving request token", e);
  }

We need to override onNewIntent(Intent intent) as this method is called once we receive intent, which has request token uri.

@Override
public void onNewIntent(Intent intent) {
  super.onNewIntent(intent); 
  prefs = PreferenceManager.getDefaultSharedPreferences(this);
  final Uri uri = intent.getData();
  if (uri != null && uri.getScheme().equals(C.OAUTH_CALLBACK_SCHEME)) {
   Log.i(C.TAG, "Callback received : " + uri);
   Log.i(C.TAG, "Retrieving Access Token");
   getAccessToken(uri);
  }
 }
Now to retrieve token and token secret from the uri
private void getAccessToken(Uri uri) {
final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
 try {
  provider.retrieveAccessToken(consumer, oauth_verifier);
  final Editor edit = prefs.edit();
  edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
  edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
  edit.commit();
   
  String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
  String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
   
  consumer.setTokenWithSecret(token, secret);
   
  } catch (Exception e) {
   Log.e(C.TAG, "Access Token Retrieval Error", e);
  }
 }

Through application user is navigated to below screens and asked to grant permission to obtain access token.


To get the contacts just make a call


String jsonOutput = makeSecuredReq(C.GET_CONTACTS_FROM_GOOGLE_REQUEST,getConsumer(this.prefs));



0 comments:

Post a Comment