Friday, July 15, 2011

Android OAuth with Google contacts tutorial with full source code

Hi Guys,
This is not a complete guide to OAuth with Google, The Best reference I found was here:
http://code.google.com/apis/accounts/docs/OAuth_ref.html


I spent some time with OAuth, but I didn't find any working example with complete source code, only partial stuff here and there, so I wrote this simple example, that authenticate with Google Contacts Service, it can be easly adapted to authenticate with any Google Service.
This example use the signpost library, that makes life easy, so you don't have to deal with the HTTP level.


So Here is what I do:

  1. I separated the application to 2 activities, this is a must, and I learned it the hard way, because for some reason Android will not start the main activity on the BROWSABLE intent filter, so there is a secondary activity that listen to the browser callback and act on it.

    
       
        
        
        
        
       
      
    
    


  2. When clicking on the launchOauth button, the RequestTokenActivity is started.

    launchOauth.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                 startActivity(new Intent().setClass(v.getContext(), RequestTokenActivity.class));
                 
                }
            });
    
    

  3. RequestTokenActivity  starts the OAuth dance, first initializing the consumer and provider, the calling the getRequestToken(), which starts the browser with the request token URL:

    private void getRequestToken() {
      try {
       Log.d(C.TAG, "getRequestToken() called");
       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);
      }
     }
    
    


  4. The browser lunched and redirected to Google accounts Authentication page, you can see that the application name "OAuth Example" is requesting permissions to access your contacts, the user should now click on the grant access button.






    You can also notice that there is a warning on the page that states that google can't verify the application, this happens because we use anonymous consumer key and secret (in C.java)

    public static final String CONSUMER_KEY  = "anonymous";
    public static final String CONSUMER_SECRET  = "anonymous";
    

    For production grade application get your consumer key and secret from Google.


  5. After the user clicked on the grant access, the browser callback is cached in the onNewIntent method (still in RequestTokenActivity),

    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);
      }
     }
    
    


    in this callback URL we have the Verifier parameter, the getAccessToken method will first extract this Verifier, that grants a short time temporary access to get the access token, then will use it to call the provider retrieveAccessToken method:

    final String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
    ... 
    provider.retrieveAccessToken(consumer, oauth_verifier);
    
    
    

    Finally we have the access token! the concludes the OAuth dance, we now store the token and the token secret in the SharedPreferences for future use, and go back to the OAuthMain activity.


  6. In the main activity we can now click on Get Contacts button, and see the list of contacts:


    The code that is relevant to OAuth is in the makeSecuredReq (in OAuthMain.java),
    Where is create the get contacts request and sign it using the consumer we create in the getConsumer Method (using the token and the secret we stored in the previous step).

    DefaultHttpClient httpclient = new DefaultHttpClient();
         HttpGet request = new HttpGet(url);
         consumer.sign(request);
         HttpResponse response = httpclient.execute(request);
    
    

    After we have the response we parse it using JSON (which is out of the scope of this tutorial, but is quite simple).



Thats it!

So Here is the Full Source Code of this example, hope you find it useful.