RESTful Google APIs, OAuth2, and Ruby

So you’re all excited to find out that the new Google APIs use RESTful methods, GET, PUT, PATCH, DELETE, etc.  And you’ve done some simple tests with calls that only require an inline key.  Everything looks good.  Now you want to do some scripting with Ruby, but all the examples on the Google site use the “google/api_client” gem, and that’s not very RESTful, even if it does bundle the OAuth2 class in it.

So task number one is to deal with OAuth2.  OAuth2 looks like a pain.  You’ve got to register your application, get a client key and secret code, use that to make an HTTP request for a token, and it all looks a little manual. You can read all about it elsewhere, but if you want to start accessing the Google APIs, you’re going to have to deal with it.  A great place to play around with the APIs and how they work in conjunction with OAuth2 is to use another Google resource, the OAuth2 Playground: https://developers.google.com/oauthplayground, this will show you how to define your calls, and shows all the responses.  Very handy for testing things out.

Avoiding the temptation to try to automate the manual authorization step, a little digging around and you can find someone has already done the heavy lifting: http://adayinthepit.com/2012/07/13/google-apis-sinatra-oauth2/. To paraphrase their code into a single ruby file, we get this:

require 'sinatra'
require 'oauth2'
require 'json'

G_API_CLIENT= "{your-client-key}"
G_API_SECRET="{your-secret}"

# Scopes are space separated strings
 SCOPES = ['https://www.googleapis.com/auth/calendar'].join(' ')

def client
 client ||= OAuth2::Client.new(G_API_CLIENT, G_API_SECRET, {
 :site => 'https://accounts.google.com',
 :authorize_url => "/o/oauth2/auth",
 :token_url => "/o/oauth2/token"
 })
 end

get '/' do
 redirect client.auth_code.authorize_url(:redirect_uri => redirect_uri,:scope => SCOPES,:access_type => "offline")
 end

get '/oauth2callback' do
 access_token = client.auth_code.get_token(params[:code], :redirect_uri => redirect_uri)
 puts "Successfully authenticated with the server"

#this is where our API call is going to go
 response = access_token.get('https://www.googleapis.com/calendar/v3/calendars/{your-calendar-id}').parsed
 end

def redirect_uri
 uri = URI.parse(request.url)
 uri.path = '/oauth2callback'
 uri.query = nil
 uri.to_s
 end

In this example the script is going to retrieve the calendar metadata settings for the calendar identified by {your-calendar-id}.  Because we’ve used the “.parsed” method, it will return the metadata as a hash.  You can access the hash by normal methods, ie. response["id"]

A couple of notes here:

  • You’re going to need to register with Google to get your API access.  All of this can be done here: https://code.google.com/apis/console
  • When you create your API access ID you’ll need to define what APIs your client is going to access.  These you define in the SCOPES variable, but you’ll also need to define them in the APIs console (see above).  To find the correct string for the scopes you’ll need to dig around in the API reference for the Google API you want to use.  A good place to start digging is here: https://developers.google.com/apis-explorer/#p/, click on the API and find the link for the “reference”.
  • Because I’m not going to start trying to parse the re-direct, when you run this, you’re going to need to open a browser and point it at the defined sinatra address (normally: http://localhost:4567).  This will is open up a dialog with Google in order to validate your credentials and issue your script with an OAuth2 token, which will then execute the code in the redirect URI (/oauth2callback).

So that’s the way most of the GET calls are going to be handled, but what about POST, PUT, PATCH, and DELETE?  You’re going to need to start passing parameters.  Let’s see an example also using the calendar API, where we create an event in our calendar.

To add a calendar event we need to use a POST method, fortunately the OAuth2 class provides methods for all these calls.

response= access_token.post('https://www.googleapis.com/calendar/v3/calendars/{your-calendar-id}/events') do |request|
 request.headers['Content-Type'] = 'application/json'
 request.body='{"end": {"dateTime": "2013-07-21T10:30:00.0z"},"start": {"dateTime": "2013-07-20T10:30:00.0z"}}'
 end
 # check response.status, works if it's 200
 json = JSON.parse(response.body)
 #access a specific response value
 puts json['id']

Note that we’ve removed the “.parsed” method from the access_token method and added some parameters to the inherited faraday client HTTP object’s request variable.  The addition of “Content-Type” allows us to pass the parameters as json, as well as receive the response in that format.  Again, playing around in the OAuth2 playground (see above) can really help speed up getting your json data formatting squared away.

Leave a Reply

Your email address will not be published. Required fields are marked *