Accessing Google API using Service Account in Node.js

January 16, 2014 / Node.js, Mad Coding

Integrating Google API into a node.js application is fairly straightforward.

First step is to include the googleapis module in your application:

npm install googleapis

Then you need to specify the API and version you want to use. Below I show the usage for Google+ Sign-In:

var googleapis = require('googleapis');

var client;
googleapis
    .discover('plus', 'v1')
    .execute(function(err, data) {
        client = data;
    });

If you make use of the code retrieved from client side in order to obtain an OAuth token, then the API call would look something like this:

var oauth2 = new googleapis.OAuth2Client(CLIENT_ID, CLIENT_SECRET, 'postmessage');
oauth2.getToken(code, function(err, tokens) {

    oauth2.credentials = tokens;
    client.plus.people.get({
        userId: 'me'
    })
    .withAuthClient(oauth2)
    .execute(function(err, result) {
    });
});

What if you want to use a Service Account that doesn’t require interaction with user & browser? For example, if you want to access Google Analytics programmatically?

Well, what you’ll need to use is the JWT (JSON Web Token) method. Doing it this way wasn’t well documented, so I want to share how it’s done. I figured out how to do this through googleapis module’s test code. This is also another reason why I want people to write tests.

First, you should have gotten a .p12 file and a secret to decrypt the file when you created the service account in Google API console. Run the following command to decrypt the p12 file.

openssl pkcs12 -in googleapi-privatekey.p12 -out googleapi-privatekey.pem -nocerts -nodes

Second, in your node.js code, you’ll instantiate googleapis.auth.JWT with the path to the decrypted key file.

var CLIENT_ID = env.googleapis.client_id;
var CLIENT_SECRET = env.googleapis.client_secret;
var oauth2 = new googleapis.OAuth2Client(CLIENT_ID, CLIENT_SECRET, 'postmessage');

var SERVICE_ACCOUNT_EMAIL = 'email@serviceaccount.com';
var SERVICE_ACCOUNT_KEY_FILE = '/path/to/decrypted/key/file';
var jwt = new googleapis.auth.JWT(
        SERVICE_ACCOUNT_EMAIL,
        SERVICE_ACCOUNT_KEY_FILE,
        null,
        ['https://www.googleapis.com/auth/analytics.readonly']);

Lastly, obtain a client for the API you want to access and then call jwt.authorize to obtain an access token. With the access token in hand, you can give it to oauth and set it as the auth client.

var client;
googleapis
    .discover('analytics', 'v3')
    .execute(function(err, data) {
        client = data;

        jwt.authorize(function(err, result) {
            oauth2.setCredentials({
                access_token: result.access_token
            });

            client.analytics.data.ga.get({
                "ids": "ga:########",
                "start-date": 'YYYY-MM-DD',
                "end-date": 'YYYY-MM-DD',
                "metrics": "ga:visits"
            })
            .withAuthClient(oauth2)
            .execute(function(err, result) {
            });
        });
    });

That’s all! Hope it helps.