Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
node-gapitoken
==============

Node.js module for Google API service account authorization (Server to Server flow).
Node.js module for Google API service account authorization (Server to Server flow).

[![Build Status](https://travis-ci.org/bsphere/node-gapitoken.svg)](https://travis-ci.org/bsphere/node-gapitoken)

Expand All @@ -10,23 +10,23 @@ Installation
------------

npm install gapitoken

Usage
-----

var GAPI = require('gapitoken');

var gapi = new GAPI({
iss: 'service account email address from Google API console',
scope: 'space delimited list of requested scopes',
keyFile: 'path to private_key.pem'
keyFile: 'path to private_key.p12'
}, function(err) {
if (err) { return console.log(err); }

gapi.getToken(function(err, token) {
if (err) { return console.log(err); }
console.log(token);
});
});
});

Another option is to pass the private key as a string
Expand All @@ -48,21 +48,30 @@ Another option is to pass the private key as a string
gapi.getToken(function(err, token) {
if (err) { return console.log(err); }
console.log(token);
});
});
});


* for using node-gapitoken to access Google Cloud Storage see https://github.com/bsphere/node-gcs

Creating a Private key file
---------------------------

1) Login to Google API Console, and under "API Access" create a "service account" for your project.

2) Download the .p12 private key file
2) Download the .p12 private key file.

3) Reference the file using the `keyFile` property as in the example above or, if you’ve already loaded the file yourself, pass it in via the `key` property as a base64-encoded string.

*A short note on .p12 and .pem files:* the .p12 file is an encoded format for storing your key. If you’d like to pre-decode it, you can convert it to a .pem file on the command line:

```shell
> openssl pkcs12 -in key.p12 -out key.pem -nocerts

3) Convert the .p12 file to .pem: `openssl pkcs12 -in key.p12 -out key.pem -nocerts`
# Note: you’ll have to set a passphrase for the file. To remove it:
> openssl rsa -in key.pem -out key.pem
```

NOTE: You must set a passphrase for the .pem file
The resulting file can then be used for the `keyFile` or `key` properties just like the .p12 file.

4) Remove the passphrase from the .pem file: `openssl rsa -in key.pem -out key.pem`
(In older versions of this library, this step was required. P12 support is now built-in.)
19 changes: 17 additions & 2 deletions gapitoken.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var jws = require('jws');
var fs = require('fs');
var request = require('request');
var p12ToPem = require('p12-to-pem');

var GAPI = function(options, callback) {
this.token = null;
Expand All @@ -18,12 +19,12 @@ var GAPI = function(options, callback) {
process.nextTick(function() {
fs.readFile(options.keyFile, function(err, res) {
if (err) { return callback(err); }
self.key = res;
self.key = decodeKey(res);
callback();
});
});
} else if (options.key) {
this.key = options.key;
this.key = decodeKey(options.key);
process.nextTick(callback);
} else {
callback(new Error("Missing key, key or keyFile option must be provided!"));
Expand Down Expand Up @@ -99,4 +100,18 @@ GAPI.prototype.getAccessToken = function(callback) {
});
};

// Takes either a raw, unprotected key or a password-protected PKCS12 file
// containing a private key and returns the key.
function decodeKey(key) {
var keyString = key.toString();
var maybeP12 = keyString.indexOf("PRIVATE KEY-----") === -1;
if (maybeP12) {
// Google's PKCS12 files use the password "notasecret"
return p12ToPem(key, "notasecret");
}
else {
return keyString;
}
}

module.exports = GAPI;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"readmeFilename": "README.md",
"dependencies": {
"jws": "~3.0.0",
"request": "^2.54.0"
"request": "^2.54.0",
"p12-to-pem": "^1.0.1"
},
"devDependencies": {
"mocha": "^2.2.5"
Expand Down
44 changes: 37 additions & 7 deletions test/auth-with-google.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,64 @@ var path = require('path');
var assert = require('assert');
var GAPI = require('../gapitoken.js');

var pemPath = path.join(__dirname, 'test-key.pem');
var keyPath = path.join(__dirname, 'test-key');

describe('Authenticating with Google', function() {
it('should work with a .pem file', function(done) {
var gapi = new GAPI({
iss: "985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com",
iss: '985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com',
scope: 'https://www.googleapis.com/auth/bigquery',
keyFile: pemPath
keyFile: keyPath + '.pem'
}, function(error) {
if (error) { return done(error); }

gapi.getToken(function(error, token) {
assert.ok(token, "Got a token");
assert.ok(token, 'Got a token');
done(error);
});
});
});

it('should work with an RSA string', function(done) {
var gapi = new GAPI({
iss: "985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com",
iss: '985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com',
scope: 'https://www.googleapis.com/auth/bigquery',
key: fs.readFileSync(pemPath)
key: fs.readFileSync(keyPath + '.pem')
}, function(error) {
if (error) { return done(error); }

gapi.getToken(function(error, token) {
assert.ok(token, "Got a token");
assert.ok(token, 'Got a token');
done(error);
});
});
});

it('should work with a .p12 file', function(done) {
var gapi = new GAPI({
iss: '985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com',
scope: 'https://www.googleapis.com/auth/bigquery',
keyFile: keyPath + '.p12'
}, function(error) {
if (error) { return done(error); }

gapi.getToken(function(error, token) {
assert.ok(token, 'Got a token');
done(error);
});
});
});

it('should work with an base64-encoded p12 string', function(done) {
var gapi = new GAPI({
iss: '985952909795-p560igbg1r2hjaagrpeust4sqca9vhi8@developer.gserviceaccount.com',
scope: 'https://www.googleapis.com/auth/bigquery',
key: fs.readFileSync(keyPath + '.p12').toString("base64")
}, function(error) {
if (error) { return done(error); }

gapi.getToken(function(error, token) {
assert.ok(token, 'Got a token');
done(error);
});
});
Expand Down
Binary file added test/test-key.p12
Binary file not shown.