ran-boilerplate
Version:
React . Apollo (GraphQL) . Next.js Toolkit
403 lines (338 loc) • 11.5 kB
JavaScript
var assert = require('assert');
var fs = require('fs');
var GoogleToken = require('../lib/index.js');
var EMAIL = 'example@developer.gserviceaccount.com';
var KEYFILE = './test/assets/key.pem';
var P12FILE = './test/assets/key.p12';
var KEYFILEJSON = './test/assets/key.json';
var KEYFILENOEMAILJSON = './test/assets/key-no-email.json';
var KEYCONTENTS = fs.readFileSync(KEYFILE);
var KEYJSONCONTENTS = fs.readFileSync(KEYFILEJSON);
var SCOPE1 = 'https://www.googleapis.com/auth/urlshortener';
var SCOPE2 = 'https://www.googleapis.com/auth/drive';
var SCOPES = [SCOPE1, SCOPE2];
var GOOGLE_TOKEN_URL = 'https://accounts.google.com/o/oauth2/token';
var GOOGLE_REVOKE_TOKEN_URL = 'https://accounts.google.com/o/oauth2/revoke?token=';
var TESTDATA = {
email: 'email@developer.gserviceaccount.com',
scope: 'scope123', // or space-delimited string of scopes
key: 'abc123key'
};
var TESTDATA_KEYFILE = {
email: 'email@developer.gserviceaccount.com',
scope: 'scope123', // or space-delimited string of scopes
keyFile: KEYFILE
};
var TESTDATA_KEYFILENOEMAIL = {
scope: 'scope123', // or space-delimited string of scopes
keyFile: KEYFILE
};
var TESTDATA_KEYFILEJSON = {
scope: 'scope123', // or space-delimited string of scopes
keyFile: KEYFILEJSON
};
var TESTDATA_KEYFILENOEMAILJSON = {
scope: 'scope123', // or space-delimited string of scopes
keyFile: KEYFILENOEMAILJSON
};
var TESTDATA_P12 = {
email: 'email@developer.gserviceaccount.com',
scope: 'scope123', // or space-delimited string of scopes
keyFile: P12FILE
};
var TESTDATA_P12_NO_EMAIL = {
scope: 'scope123', // or space-delimited string of scopes
keyFile: P12FILE
};
var MIME = {
lookup: function(filename) {
if (filename === P12FILE) {
return 'application/x-pkcs12';
} else if (filename === KEYFILEJSON) {
return 'application/json';
} else {
return '';
}
}
};
var noop = function() {};
describe('gtoken', function() {
it('should exist', function() {
assert.equal(typeof GoogleToken, 'function');
});
it('should work without new or options', function() {
var gtoken = GoogleToken();
assert(gtoken);
});
describe('.iss', function() {
it('should be set from email option', function() {
var gtoken = GoogleToken({
email: EMAIL
});
assert.equal(gtoken.iss, EMAIL);
assert.equal(gtoken.email, undefined);
});
it('should be set from iss option', function() {
var gtoken = GoogleToken({
iss: EMAIL
});
assert.equal(gtoken.iss, EMAIL);
});
it('should be set from email option over iss option', function() {
var gtoken = GoogleToken({
iss: EMAIL,
email: 'another' + EMAIL
});
assert.equal(gtoken.iss, 'another' + EMAIL);
});
});
describe('.scope', function() {
it('should accept strings', function() {
var gtoken = GoogleToken({
scope: 'hello world'
});
assert.equal(gtoken.scope, 'hello world');
});
it('should accept array of strings', function() {
var gtoken = GoogleToken({
scope: ['hello', 'world']
});
assert.equal(gtoken.scope, 'hello world');
});
});
describe('.hasExpired()', function() {
it('should exist', function() {
var gtoken = GoogleToken();
assert.equal(typeof gtoken.hasExpired, 'function');
});
it('should detect expired tokens', function() {
var gtoken = GoogleToken();
assert(gtoken.hasExpired(), 'should be expired without token');
gtoken.token = 'hello';
assert(gtoken.hasExpired(), 'should be expired without expires_at');
gtoken.expires_at = (new Date().getTime()) + 10000;
assert(!gtoken.hasExpired(), 'shouldnt be expired with future date');
gtoken.expires_at = (new Date().getTime()) - 10000;
assert(gtoken.hasExpired(), 'should be expired with past date');
gtoken.expires_at = (new Date().getTime()) + 10000;
gtoken.token = null;
assert(gtoken.hasExpired(), 'should be expired with no token');
});
});
describe('.revokeToken()', function() {
it('should exist', function() {
var gtoken = GoogleToken();
assert.equal(typeof gtoken.revokeToken, 'function');
});
it('should run ._configure()', function(done) {
var gtoken = GoogleToken();
gtoken.token = 'woot';
gtoken._request = function(opts, cb) {
assert.equal(opts, GOOGLE_REVOKE_TOKEN_URL + 'woot');
cb();
};
gtoken._configure = function(options) {
assert(options);
};
gtoken.revokeToken(done);
});
it('should return error when no token set', function(done) {
var gtoken = GoogleToken();
gtoken.token = null;
gtoken.revokeToken(function(err) {
assert(err && err.message);
done();
});
});
});
describe('.getToken()', function() {
it('should exist', function() {
var gtoken = GoogleToken();
assert.equal(typeof gtoken.getToken, 'function');
});
it('should run jws.sign() with correct object', function(done) {
var gtoken = GoogleToken(TESTDATA);
gtoken._signJWT = function(data) {
assert.deepEqual(data.header, {
alg: 'RS256',
typ: 'JWT'
});
assert(data.payload);
assert.equal(data.payload.iss, 'email@developer.gserviceaccount.com');
assert.equal(data.payload.scope, 'scope123');
assert.equal(data.payload.aud, GOOGLE_TOKEN_URL);
assert.equal(data.secret, 'abc123key');
done();
};
gtoken.getToken(noop);
});
it('should read .pem keyFile from file', function(done) {
var gtoken = GoogleToken(TESTDATA_KEYFILE);
gtoken._mime = MIME;
gtoken._signJWT = function(opts, cb) {
cb();
};
gtoken._request = function(opts, cb) {
cb();
};
gtoken.getToken(function(err, token) {
assert.deepEqual(gtoken.key, KEYCONTENTS);
done();
});
});
it('should return error if iss is not set with .pem', function(done) {
var gtoken = GoogleToken(TESTDATA_KEYFILENOEMAIL);
gtoken.getToken(function(err) {
assert.strictEqual(err.code, 'MISSING_CREDENTIALS');
done();
});
});
it('should read .json key from file', function(done) {
var gtoken = GoogleToken(TESTDATA_KEYFILEJSON);
gtoken._mime = MIME;
gtoken._signJWT = function(opts, cb) {
cb();
};
gtoken._request = function(opts, cb) {
cb();
};
gtoken.getToken(function(err, token) {
var parsed = JSON.parse(KEYJSONCONTENTS);
assert.deepEqual(gtoken.key, parsed.private_key);
assert.deepEqual(gtoken.iss, parsed.client_email);
done();
});
});
it('should return error if iss is not set with .json', function(done) {
var gtoken = GoogleToken(TESTDATA_KEYFILENOEMAILJSON);
gtoken.getToken(function(err) {
assert.strictEqual(err.code, 'MISSING_CREDENTIALS');
done();
});
});
it('should return cached token if not expired', function(done) {
var gtoken = GoogleToken(TESTDATA);
gtoken.token = 'mytoken';
gtoken.expires_at = new Date().getTime() + 10000;
gtoken.getToken(function(err, token) {
assert.equal(token, 'mytoken');
done();
});
});
it('should run mime.lookup if keyFile given', function(done) {
var gtoken = GoogleToken(TESTDATA_KEYFILE);
gtoken._mime = {
lookup: function(filename) {
assert.equal(filename, KEYFILE);
done();
}
};
gtoken._request = function(opts, callback) {
callback();
};
gtoken.getToken(noop);
});
it('should run gp12pem if .p12 file is given', function(done) {
var gtoken = GoogleToken(TESTDATA_P12);
gtoken._gp12pem = function(filename, callback) {
assert.equal(filename, P12FILE);
done();
};
gtoken._mime = MIME;
gtoken.getToken(noop);
});
it('should return error if iss is not set with .p12', function(done) {
var gtoken = GoogleToken(TESTDATA_P12_NO_EMAIL);
gtoken.getToken(function(err) {
assert.strictEqual(err.code, 'MISSING_CREDENTIALS');
done();
});
});
describe('request', function() {
it('should be run with correct options', function(done) {
var gtoken = GoogleToken(TESTDATA);
gtoken._signJWT = function sign(opts, callback) {
callback(null, 'signedJWT123');
};
gtoken._request = function(options, callback) {
assert.deepEqual(options, {
method: 'post',
url: GOOGLE_TOKEN_URL,
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: 'signedJWT123'
}
});
callback();
};
gtoken.getToken(done);
});
it('should set and return correct properties on success', function(done) {
var gtoken = GoogleToken(TESTDATA);
var RESPBODY = JSON.stringify({
access_token: 'accesstoken123',
expires_in: 3600,
token_type: 'Bearer'
});
gtoken._request = function(options, callback) {
callback(null, 'res', RESPBODY);
};
gtoken._signJWT = function(opts, callback) {
callback(null, 'signedJWT123');
};
gtoken.getToken(function(err, token) {
assert.deepEqual(gtoken.raw_token, JSON.parse(RESPBODY));
assert.equal(gtoken.token, 'accesstoken123');
assert.equal(gtoken.token, token);
assert.equal(err, null);
assert(gtoken.expires_at >= (new Date()).getTime());
assert(gtoken.expires_at <= (new Date()).getTime() + (3600 * 1000));
done();
});
});
it('should set and return correct properties on error', function(done) {
var ERROR = new Error('An error occurred.');
var gtoken = GoogleToken(TESTDATA);
var RESPBODY = JSON.stringify({
access_token: 'accesstoken123',
expires_in: 3600,
token_type: 'Bearer'
});
gtoken._request = function(options, callback) {
callback(ERROR);
};
gtoken._signJWT = function sign(opts, callback) {
callback(null, 'signedJWT123');
};
gtoken.getToken(function(err, token) {
assert.equal(gtoken.raw_token, null);
assert.equal(gtoken.token, null);
assert.equal(gtoken.token, token);
assert.equal(err, ERROR);
assert.equal(gtoken.expires_at, null);
done();
});
});
it('should include error_description from remote error', function(done) {
var gtoken = GoogleToken(TESTDATA);
var ERROR = 'error_name';
var DESCRIPTION = 'more detailed message';
var RESPBODY = JSON.stringify({
error: ERROR,
error_description: DESCRIPTION
});
gtoken._request = function(options, callback) {
callback(null, {}, RESPBODY);
};
gtoken._signJWT = function(opts, callback) {
callback(null, 'signedJWT123');
};
gtoken.getToken(function(err, token) {
assert(err instanceof Error);
assert.equal(err.message, ERROR + ': ' + DESCRIPTION);
done();
});
});
});
});
});