OAuth and Django 1/3 – Google Data API

Recently, I found myself wrestling with the OAuth implementations of several social sites. Now that I have completed integrating OAuth services from Twitter, LinkedIn, and Google it has made my app much better for the end user. However, I had a fair amount of difficulty integrating them all, as each provider implemented the handshake differently. So in the event that someone else is doing this I decided to write my first set of tutorials (three total) on what I did.

The most difficult to figure out, by far, was Google’s OAuth 1.0 implementation, and is the subject of this post. The root of these difficulties was the one off’s that I ran into for different services and libraries in Google’s APIs. The examples provided by Google did not seem match the Contact API that I was using.  I finished this code before Google released OAuth 2.0.

Registering Domain

The first step to doing anything OAuth with Google APIs is to register your domain at https://www.google.com/accounts/ManageDomains.

After registering your domain you can grab your OAuth Consumer Key and Secret, which are used for the OAuth handshake with Google. You can also upload a certificate, but we are not going to do that here

Django OAuth Handshake

There are several steps to OAuth Handshake:

  1. Set OAuth input parameters
  2. Fetch OAuth Request token
  3. Set the fetched OAuth token
  4. Generate OAuth authorization URL
  5. Upgrade to an OAuth access token


Before we get to the coding here are all of the requisite libraries and settings that the code uses.  All of the libraries other than gdata can be installed using pip.


  • Python==2.6
  • Django==1.2.4
  • oauth==1.2.0
  • gdata==2.0.13 (http://code.google.com/p/gdata-python-client/downloads/detail?name=gdata-2.0.13.zip)

Variables in settings.py

# used by google to call your app after the user grants access
GOOGLE_CALLBACK_URL = u'http://localhost:8080/google_oauth_verifier'
# used during the handshake process
GOOGLE_CONSUMER_KEY         = u'<< your domain >>'
GOOGLE_CONSUMER_SECRET      = u'<< your secret >>'

For completeness, I also had this in the urls.py

# your app calls this one
(r'^google_oauth/$', '<< your app >>.views.google_oauth'),
(r'^google_oauth_verifier', '<< your app >>.views.google_oauth_verifier'),

Django Code

The following code references the handshake steps I mentioned earlier.

def google_oauth(request):
    """Google oauth stuff getting google contacts"""
    gd_client = gdata.contacts.service.ContactsService()

    #STEP 1: Set OAuth input parameters.
        settings.GOOGLE_CONSUMER_KEY, consumer_secret=settings.GOOGLE_CONSUMER_SECRET)

    #STEP 2: Fetch OAuth Request token.
    request_token = gd_client.FetchOAuthRequestToken()

    #STEP 3: Set the fetched OAuth token.
    request.session['gd_client'] = gd_client

    #STEP 4: Generate OAuth authorization URL.
    auth_url = gd_client.GenerateOAuthAuthorizationURL(

    return HttpResponseRedirect(auth_url)

def google_oauth_verifier(request):
    """google_oauth_verifier this is what gets called by the google callback"""
    gd_client = request.session['gd_client']
    #STEP 5: Upgrade to an OAuth access token

    request.session['gd_client'] = gd_client

    return HttpResponseRedirect('/yourapp/somewhere')

This is the code that should correspond to your ‘/yourapp/somewhere/’ url, it is what checks for the gd_client and fires off the OAuth handshake if needed.

        if not request.session.__contains__('gd_client'):
            return HttpResponseRedirect(Site.objects.get_current().domain + '/accounts/google_oauth')

        gd_client = request.session['gd_client']


That should about do it.  I hope this helps anyone that is attempting to do this, if you found it helpful or have any questions just leave a comment.  This was my first tutorial so it may not be exactly crystal clear ;P.



I have (finally) updated my resume and publication list. If you would like a more complete version of my resume please email me at bhanraha [at] vt [dot] edu.

Testing out WordPress

I am in the process of switching over to WordPress.  I apologize if you are coming here looking for specific information about me, I am working on getting all of my content back up right now.