Posted by on January 15, 2017

Accessing the Drive API

Accessing a Google API is a multi-step process.  Fortunately the repetitive OAuth2 tasks can be mostly done behind the scenes hidden inside libraries or your “write once” code.  The steps entail:

  1. Decide what API (or APIs) you want your application to access
  2. Figure out what ‘scopes’ you want to use
  3. Get an authentication url for your client id and scopes
  4. Get an authentication code
  5. Get a authentication token
  6. Use the valid token to authenticate API requests
  7. Make your API requests
  8. As needed, refresh the token

Items 1, 2, and 7 are really the only ones that you need to worry about.  Everything else is OAuth2.  Understanding what is going on at the OAuth2 level is incredibly helpful especially when you need to debug.  We’ll go through each of these steps.

A working example

Here is a working example to get a file list from your Google drive.  We’ll break this apart piece by piece below.  Note that this is NOT how I would write a script for day to day use.  This is a “hardcoded and unrolled” version for showing how to authenticate and use the APIs.

 
use strict;
use warnings;
use LWP::Authen::OAuth2;
use JSON;

# The client id and secret from the client_secret.json file
my $client_id = "954250104053-k1e603q9r8fp6c7dt6q3a5k2j64h47vv.apps.googleusercontent.com";
my $client_secret = "qFFFvAhRROpaom6pU_Z9Pp3r";

# construct the OAuth2 object 
my $oauth2 = LWP::Authen::OAuth2->new(
  client_id        => $client_id,                  # from client_secret.json
  client_secret    => $client_secret,              # from client_secret.json
  service_provider => "Google",
  redirect_uri     => "urn:ietf:wg:oauth:2.0:oob", # from client_secret.json
);

# The scope of access we are requesting
my $scope = "https://www.googleapis.com/auth/drive";

# get the authentication url, give the user an opportunity to navigate to the 
# url, copy the auth code, and paste it
my $url = $oauth2->authorization_url( scope => $scope );

print "Authorization URL: $url\n";

print "Navigate to the above url and enter the returned auth code here: ";
my $code = <STDIN>;
chomp $code;

# Go get the auth tokens
$oauth2->request_tokens(code => $code);

# Finally make the API request
my $resp = $oauth2->get( "https://www.googleapis.com/drive/v2/files" );

if ( $resp->code() != 200 )
{
  die "Error: " . $resp->code();
}

# The content is a JSON response 
my $data = decode_json($resp->content());

# Iterate over the files and list
for my $file ( @{$data->{items}} )
{
  print $file->{title}, "\n";
}

What API to use?

This should be straightforward.  What do you want to do?  Search for files on you Google Drive?  Access Sheets data?  Manage Group membership?  Integrate the URL Shortener into your app?  What you want to access will determine the API (or APIs) you will need.  The APIs are well documented on developer.google.com.  Search for your API there.  We will be using the Google Drive API which is documented here.

Once you know the API you then need to decide what methods you want to use.  The APIs are split into Resources and the Methods that act on those resources.  For example, one of the resources for Google Drive is ‘Files’ (imagine that).  Click on the Files resource in the documentation and you can see the available Methods.

We want to get a file listing so the method we are interested in is ‘list‘.  The documentation tells us that we need to make a GET request to  https://www.googleapis.com/drive/v2/files.  But first we need to authenticate.

Which Scope?

When you ask Google for permissions to access the API you need to ask for a specific scope of access.  For Drive, this page lists the possible scopes.  The guideline is to ask for the most restrictive scope possible.  In our case we just want to get a list of files so “https://www.googleapis.com/auth/drive.readonly” will fit our needs nicely.

Get an Authentication URL

Use the OAuth2 object to get the authentication URL based on the desired scope.  For example:

my $scope = "https://www.googleapis.com/auth/drive.readonly";

my $url = $oauth2->authorization_url( scope => $scope );

Get an authentication Code

Next, navigate to the authentication URL. Google will have you log in (be sure to log into the correct account if you have multiple) and provide you with a code for the next step in the process.

Get the authentication token

At this point, getting the token is a simple call, with a whole lot of stuff hidden behind the scenes:

$oauth2->request_tokens(code => $code);

At this point the $oauth2 object will fetch and set the auth token.  Once you get here you will be all set to make calls to the requested API.

Make the API Call

my $resp = $oauth2-&gt;get( "https://www.googleapis.com/drive/v2/files" );

if ( $resp-&gt;code() != 200 )
{
  die "Error: " . $resp-&gt;code();
}

# The content is a JSON response 
my $data = decode_json($resp-&gt;content());

# Iterate over the files and list
for my $file ( @{$data-&gt;{items}} )
{
  print $file-&gt;{title}, "\n";
}

The API call returns a JSON payload.  A 200 response code indicates success.  Use the JSON module to make quick work of the parsing and then iterate over the resource structure.

Conclusion

With the above guidance on OAuth2 and the API calls it is possible to access any of the APIs. Though it gets the job done, I would much prefer to not have to work at such a low level all the time.  In future articles we’ll explore:

  • The Auto-Discovery API for autogenerating a more perl like way to access the APIs
  • Google::API::Client, a module that provides a mechanism to do exactly that
  • Any other things that trip me up or I discover along the way

Once you get past the tricky part of authentication, everything is straightforward.  Hopefully this help cut through that fog a bit to help others get to the good stuff a bit faster.

Posted in: google api, oauth2, perl

Comments

Be the first to comment.

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*