Friday, March 4, 2011

[G] Client Side Authorization in the API

| More

Google Analytics Blog: Client Side Authorization in the API

This post is inspired by Henrik who posted a comment on last week’s Mastering Unique Visitor blog post. His question was, “Most API users would not create web apps but rather easily access their data without account authentication. Is this possible? Could you describe it?”

Great question Henrik! While you do have to authenticate to the Google Analytics Data Export API in order to access data, your application doesn’t have to re-authenticate every time. In this post we show you an easy way to re-use tokens and give you a Python class to simplify the process.

(Note: we recommend you follow the actual sample code to see how all the pieces described below work together.)

Just like you have to log in to view Google Analytics data, you also have to grant an application access to your Analytics data when you use the the API. This is called authorization and is done through the Google Accounts API.

Different Authorization Protocols
When you log into the Analytics interface, your login credentials are protected from being exposed. In the same way, you use the Google Accounts API to protect credentials by requesting an authorization token in place of actual user names and passwords. That authorization token is used in the header of each Google Analytics API request.

There are a two authorization routines that applications can choose in order to obtain this token:

Client Login - a legacy, Google proprietary, authorization routine. The user of your application must supply their user name and password in your application. Your application communicates to Analytics on the user’s behalf and retrieves an authentication token. This token only lasts for 14 days. The issue with this method is that if the token is stolen, others can use it and the user has no way to revoke it.

OAuth For Installed Apps - is Google-supported open standard. Client apps must send users to a web page where the user logs in and grants account access to the application. The web page presents the user with a verification code which they must input back into the application. The application can exchange this verification code for a long-lived token. The long-lived token lasts forever and can be revoked by the user through the Google Accounts interface. This routine is more secure because a user can revoke the token and prevent an application from accessing their data at any time.

Obviously OAuth For Installed Apps is a better way to generate authorization tokens.

Token Management
Because authorization tokens are valid for multiple requests, applications should reuse them until they become invalid. For a client-side app, this usually means saving the token to disk. Here’s the logic to handle this in python:

def GetAuthToken(self):
  if self.auth_token:
    return self.auth_token

  self.auth_token =

  if not self.auth_token:
    self.auth_token = self.RequestAuthToken()

  return self.auth_token

Here the code tries to load a token from disk. If it exists, the token is set in the client object that makes requests to Google Analytics. If the token does not exist, the code tries to obtain it from the Google Accounts API, then save it to disk...all pretty easy.

Retrieving a New OAuth Token

To get a new OAuth token, the code uses helper methods in the Python Client Library. The my_client parameter is a reference to the object provided by the Google Data Python Client Library. It handles all the logic to make requests to the Google Analytics API.

First, the my_client object is used retrieve the URL to the OAuth authorization end point. Next it retrieves a request_token from the Google Accounts API and use that token to generate a URL for the user to go to.

The URL is printed to the screen and the code tries to pop open a browser and take the user directly there. The user will be prompted to login and grant access to the application. Once complete, the web page gives the user a verification code.

The code prompts the user for the verification code, and once inputted, the application uses it to get a long-lived access token. This access token will be valid until the user revokes the token.

Here’s the sample code:

def GetAuthToken(self, my_client):
  url = ('%s?xoauth_displayname=%s' %
      (gdata.gauth.REQUEST_TOKEN_URL, self.my_client.source))

  request_token = self.my_client.GetOAuthToken(

  verify_url = request_token.generate_authorization_url(

  print 'Please log in and/or grant access at: %s\n' % verify_url

  request_token.verifier =
      raw_input('Please enter the verification code '
                'on the success page: ')

    return self.my_client.GetAccessToken(request_token)

  except gdata.client.RequestError, err:
    raise AuthError(msg='Error upgrading token: %s' % err)

Once we have the long-lived token, it’s returned and the GetAuthToken method above saves it to disk.

Making Google Analytics API Requests

To use the token retrieved above, we simply set it in the object:

  my_client.auth_token = my_auth.GetAuthToken()

except auth.AuthError, error:
  print error.msg

At this point an application can use the client object to retrieve data from the Google Analytics API. Because a user can revoke a token from the Google Accounts API and the code loads the token from disk, there can be a case where the token on the disk is invalid. In this case, the Google Analytics API returns a 401 status code and the client library raises a gdata.client.Unauthorized exception. If this happens, we need to catch the exception, delete the saved token and prompt the user to get a new token.

  feed = my_client.GetDataFeed(data_query)

except gdata.client.Unauthorized, error:
  print '%s\nDeleting token file.' % error

So there you have it, a quick overview of client side authorization with the Google Analytics API. As we mentioned above, you can view and use the full sample code.

Submit your own questions
We’re thrilled to get feedback from our developers. You guys rock! If you have a question about our API, like Henrik, please leave it in our comments. We’ll go through them and try to highlight the code solutions.

Posted by Nick Mihailovski, Google Analytics API Team

No comments: