From 2b5ebfc85cfdd2445a11789f788884d450489066 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 24 Mar 2016 17:27:05 -0700 Subject: [PATCH 1/8] Make Oauth2Client#request retry on auth errors as documented --- lib/auth/oauth2client.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/auth/oauth2client.js b/lib/auth/oauth2client.js index e044846..af75596 100644 --- a/lib/auth/oauth2client.js +++ b/lib/auth/oauth2client.js @@ -338,9 +338,21 @@ OAuth2Client.prototype.revokeCredentials = function(callback) { OAuth2Client.prototype.request = function(opts, callback) { var that = this; + // Callbacks will close over this to ensure that we only retry once + var retry = true; + // Hook the callback routine to call the _postRequest method. var postRequestCb = function(err, body, resp) { - that._postRequest(err, body, resp, callback); + // Automatically retry 401 and 403 responses + if (retry && err && (err.code == 401 || err.code == 403)) { + /* It only makes sense to retry once, because the retry is intended to + * handle expiration-related failures. If refreshing the token does not + * fix the failure, then refreshing again probably won't help */ + retry = false; + that.getRequestMetadata(unusedUri, authCb); + } else { + that._postRequest(err, body, resp, callback); + } }; var authCb = function(err, headers, response) { From 3ce01ec28a2d2cb6cf3bbdd7269e6bc805fef23f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 25 Mar 2016 11:00:42 -0700 Subject: [PATCH 2/8] Added test for OAuth2Client#request retry, fixed implementation --- lib/auth/oauth2client.js | 9 +++++++-- test/test.jwt.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/auth/oauth2client.js b/lib/auth/oauth2client.js index af75596..aa7e702 100644 --- a/lib/auth/oauth2client.js +++ b/lib/auth/oauth2client.js @@ -344,12 +344,17 @@ OAuth2Client.prototype.request = function(opts, callback) { // Hook the callback routine to call the _postRequest method. var postRequestCb = function(err, body, resp) { // Automatically retry 401 and 403 responses - if (retry && err && (err.code == 401 || err.code == 403)) { + // if err is set, then getting credentials failed, and retrying won't help + if (retry && !err && resp && + (resp.statusCode == 401 || resp.statusCode == 403)) { /* It only makes sense to retry once, because the retry is intended to * handle expiration-related failures. If refreshing the token does not * fix the failure, then refreshing again probably won't help */ retry = false; - that.getRequestMetadata(unusedUri, authCb); + // Force token refresh + that.refreshAccessToken(function() { + that.getRequestMetadata(unusedUri, authCb); + }); } else { that._postRequest(err, body, resp, callback); } diff --git a/test/test.jwt.js b/test/test.jwt.js index 9b803b8..5966746 100644 --- a/test/test.jwt.js +++ b/test/test.jwt.js @@ -267,6 +267,39 @@ describe('JWT auth client', function() { }); }); + it('should refresh token if the server returns 403', function(done) { + var scope = nock('http://example.com') + .log(console.log) + .get('/access') + .reply(403); + + var auth = new googleAuth(); + var jwt = new auth.JWT( + 'foo@serviceaccount.com', + '/path/to/key.pem', + null, + ['http://example.com'], + 'bar@subjectaccount.com'); + + jwt.credentials = { + access_token: 'woot', + refresh_token: 'jwt-placeholder', + expiry_date: (new Date()).getTime() + 5000 + }; + + jwt.gtoken = { + getToken: function(callback) { + return callback(null, 'abc123'); + } + }; + + jwt.request({ uri : 'http://example.com/access' }, function() { + assert.equal('abc123', jwt.credentials.access_token); + nock.cleanAll(); + done(); + }); + }); + it('should not refresh if not expired', function(done) { var scope = nock('https://accounts.google.com') .log(console.log) From 14009b9fedb6c3fa755e4133640a39c3209fae19 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 1 Apr 2016 09:42:48 -0700 Subject: [PATCH 3/8] Capitalize constructor names everywhere to satisfy linter --- lib/auth/googleauth.js | 4 +- test/test.compute.js | 8 ++-- test/test.googleauth.js | 102 ++++++++++++++++++++-------------------- test/test.iam.js | 4 +- test/test.jwt.js | 36 +++++++------- test/test.jwtaccess.js | 10 ++-- test/test.oauth2.js | 60 +++++++++++------------ test/test.refresh.js | 22 ++++----- 8 files changed, 123 insertions(+), 123 deletions(-) diff --git a/lib/auth/googleauth.js b/lib/auth/googleauth.js index a9316e4..d8155f5 100644 --- a/lib/auth/googleauth.js +++ b/lib/auth/googleauth.js @@ -22,7 +22,7 @@ var fs = require('fs'); var os = require('os'); var path = require('path'); var util = require('util'); -var defaultTransporter = require('../transporters.js'); +var DefaultTransporter = require('../transporters.js'); /** * GoogleAuth account manager. @@ -161,7 +161,7 @@ GoogleAuth.prototype._checkIsGCE = function(callback) { callback(that._isGCE); } else { if (!that.transporter) { - that.transporter = new defaultTransporter(); + that.transporter = new DefaultTransporter(); } that.transporter.request({ method: 'GET', diff --git a/test/test.compute.js b/test/test.compute.js index c175391..08f3717 100644 --- a/test/test.compute.js +++ b/test/test.compute.js @@ -17,7 +17,7 @@ 'use strict'; var assert = require('assert'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var nock = require('nock'); nock.disableNetConnect(); @@ -27,7 +27,7 @@ describe('Initial credentials', function() { it('should create a dummy refresh token string', function () { // It is important that the compute client is created with a refresh token value filled // in, or else the rest of the logic will not work. - var auth = new googleAuth(); + var auth = new GoogleAuth(); var compute = new auth.Compute(); assert.equal('compute-placeholder', compute.credentials.refresh_token); }); @@ -37,7 +37,7 @@ describe('Compute auth client', function() { // set up compute client. var compute; beforeEach(function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); compute = new auth.Compute(); }); @@ -81,7 +81,7 @@ describe('Compute auth client', function() { describe('.createScopedRequired', function () { it('should return false', function () { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var compute = new auth.Compute(); assert.equal(false, compute.createScopedRequired()); }); diff --git a/test/test.googleauth.js b/test/test.googleauth.js index 86efe4d..7cf7832 100644 --- a/test/test.googleauth.js +++ b/test/test.googleauth.js @@ -17,7 +17,7 @@ 'use strict'; var assert = require('assert'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var nock = require('nock'); var fs = require('fs'); @@ -117,11 +117,11 @@ function doneWhen(doneCallback, count) { }; } -describe('googleAuth', function() { +describe('GoogleAuth', function() { describe('.fromJson', function () { it('should error on null json', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(null, function (err) { assert.equal(true, err instanceof Error); done(); @@ -131,7 +131,7 @@ describe('googleAuth', function() { describe('JWT token', function() { it('should error on empty json', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON({}, function (err) { assert.equal(true, err instanceof Error); done(); @@ -142,7 +142,7 @@ describe('googleAuth', function() { var json = createJwtJSON(); delete json.client_email; - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); done(); @@ -153,7 +153,7 @@ describe('googleAuth', function() { var json = createJwtJSON(); delete json.private_key; - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); done(); @@ -162,7 +162,7 @@ describe('googleAuth', function() { it('should create JWT with client_email', function (done) { var json = createJwtJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err, result) { assert.equal(null, err); assert.equal(json.client_email, result.email); @@ -172,7 +172,7 @@ describe('googleAuth', function() { it('should create JWT with private_key', function (done) { var json = createJwtJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err, result) { assert.equal(null, err); assert.equal(json.private_key, result.key); @@ -182,7 +182,7 @@ describe('googleAuth', function() { it('should create JWT with null scopes', function (done) { var json = createJwtJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err, result) { assert.equal(null, err); assert.equal(null, result.scopes); @@ -192,7 +192,7 @@ describe('googleAuth', function() { it('should create JWT with null subject', function (done) { var json = createJwtJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err, result) { assert.equal(null, err); assert.equal(null, result.subject); @@ -202,7 +202,7 @@ describe('googleAuth', function() { it('should create JWT with null keyFile', function (done) { var json = createJwtJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromJSON(json, function (err, result) { assert.equal(null, err); assert.equal(null, result.keyFile); @@ -212,7 +212,7 @@ describe('googleAuth', function() { }); describe('Refresh token', function() { it('should error on empty json', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT(); jwt.fromJSON({}, function (err) { assert.equal(true, err instanceof Error); @@ -224,7 +224,7 @@ describe('googleAuth', function() { var json = createRefreshJSON(); delete json.client_id; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT(); jwt.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -236,7 +236,7 @@ describe('googleAuth', function() { var json = createRefreshJSON(); delete json.client_secret; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT(); jwt.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -248,7 +248,7 @@ describe('googleAuth', function() { var json = createRefreshJSON(); delete json.refresh_token; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT(); jwt.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -261,7 +261,7 @@ describe('googleAuth', function() { describe('.fromStream', function () { it('should error on null stream', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromStream(null, function (err) { assert.equal(true, err instanceof Error); done(); @@ -277,7 +277,7 @@ describe('googleAuth', function() { var stream = fs.createReadStream('./test/fixtures/private.json'); // And pass it into the fromStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromStream(stream, function (err, result) { assert.equal(null, err); @@ -301,7 +301,7 @@ describe('googleAuth', function() { var stream = fs.createReadStream('./test/fixtures/refresh.json'); // And pass it into the fromStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromStream(stream, function (err, result) { assert.ifError(err); @@ -318,7 +318,7 @@ describe('googleAuth', function() { describe('._getApplicationCredentialsFromFilePath', function () { it('should error on null file path', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath(null, function (err) { assert.equal(true, err instanceof Error); done(); @@ -326,7 +326,7 @@ describe('googleAuth', function() { }); it('should error on empty file path', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath('', function (err) { assert.equal(true, err instanceof Error); done(); @@ -334,7 +334,7 @@ describe('googleAuth', function() { }); it('should error on non-string file path', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath(2, function (err) { assert.equal(true, err instanceof Error); done(); @@ -342,7 +342,7 @@ describe('googleAuth', function() { }); it('should error on invalid file path', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath('./nonexistantfile.json', function (err) { @@ -357,7 +357,7 @@ describe('googleAuth', function() { assert.equal(true, fs.lstatSync(directory).isDirectory()); // Execute. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath(directory, function (err) { @@ -368,7 +368,7 @@ describe('googleAuth', function() { it('should handle errors thrown from createReadStream', function (done) { // Set up a mock to throw from the createReadStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._createReadStream = function () { throw new Error('Hans and Chewbacca'); }; @@ -383,7 +383,7 @@ describe('googleAuth', function() { it('should handle errors thrown from fromStream', function (done) { // Set up a mock to throw from the fromStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromStream = function () { throw new Error('Darth Maul'); }; @@ -398,7 +398,7 @@ describe('googleAuth', function() { it('should handle errors passed from fromStream', function (done) { // Set up a mock to return an error from the fromStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth.fromStream = function (stream, callback) { callback(new Error('Princess Leia')); }; @@ -417,7 +417,7 @@ describe('googleAuth', function() { var json = JSON.parse(fileContents); // Now pass the same path to the auth loader. - var auth = new googleAuth(); + var auth = new GoogleAuth(); auth._getApplicationCredentialsFromFilePath('./test/fixtures/private.json', function (err, result) { @@ -436,7 +436,7 @@ describe('googleAuth', function() { it('should return false when env var is not set', function (done) { // Set up a mock to return a null path string. - var auth = new googleAuth(); + var auth = new GoogleAuth(); insertEnvironmentVariableIntoAuth(auth, 'GOOGLE_APPLICATION_CREDENTIALS', null); // The test ends successfully after 1 step has completed. @@ -453,7 +453,7 @@ describe('googleAuth', function() { it('should return false when env var is empty string', function (done) { // Set up a mock to return an empty path string. - var auth = new googleAuth(); + var auth = new GoogleAuth(); insertEnvironmentVariableIntoAuth(auth, 'GOOGLE_APPLICATION_CREDENTIALS', ''); // The test ends successfully after 1 step has completed. @@ -470,7 +470,7 @@ describe('googleAuth', function() { it('should handle invalid environment variable', function (done) { // Set up a mock to return a path to an invalid file. - var auth = new googleAuth(); + var auth = new GoogleAuth(); insertEnvironmentVariableIntoAuth(auth, 'GOOGLE_APPLICATION_CREDENTIALS', './nonexistantfile.json'); @@ -489,7 +489,7 @@ describe('googleAuth', function() { it('should handle valid environment variable', function (done) { // Set up a mock to return path to a valid credentials file. - var auth = new googleAuth(); + var auth = new GoogleAuth(); insertEnvironmentVariableIntoAuth(auth, 'GOOGLE_APPLICATION_CREDENTIALS', './test/fixtures/private.json'); @@ -523,7 +523,7 @@ describe('googleAuth', function() { var correctLocation = false; // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -547,7 +547,7 @@ describe('googleAuth', function() { var correctLocation = false; // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'HOME', 'foo'); auth._pathJoin = pathJoin; @@ -570,7 +570,7 @@ describe('googleAuth', function() { it('should fail on Windows when APPDATA is not defined', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', null); auth._pathJoin = pathJoin; @@ -592,7 +592,7 @@ describe('googleAuth', function() { it('should fail on non-Windows when HOME is not defined', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'HOME', null); auth._pathJoin = pathJoin; @@ -614,7 +614,7 @@ describe('googleAuth', function() { it('should fail on Windows when file does not exist', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -636,7 +636,7 @@ describe('googleAuth', function() { it('should fail on non-Windows when file does not exist', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'HOME', 'foo'); auth._pathJoin = pathJoin; @@ -659,7 +659,7 @@ describe('googleAuth', function() { it('should succeeds on Windows', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -686,7 +686,7 @@ describe('googleAuth', function() { it('should succeeds on non-Windows', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'HOME', 'foo'); auth._pathJoin = pathJoin; @@ -713,7 +713,7 @@ describe('googleAuth', function() { it('should pass along a failure on Windows', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -740,7 +740,7 @@ describe('googleAuth', function() { it('should pass along a failure on non-Windows', function (done) { // Set up mocks. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'HOME', 'foo'); auth._pathJoin = pathJoin; @@ -784,7 +784,7 @@ describe('googleAuth', function() { }; // Set up a new GoogleAuth and prepare it for local environment variable handling. - var auth = new googleAuth(); + var auth = new GoogleAuth(); setUpAuthForEnvironmentVariable(auth); // Ask for credentials, the first time. @@ -818,7 +818,7 @@ describe('googleAuth', function() { // Now create a second GoogleAuth instance, and ask for credentials. We should // get a new credentials instance this time. - var auth2 = new googleAuth(); + var auth2 = new GoogleAuth(); setUpAuthForEnvironmentVariable(auth2); // Step 2 has completed. @@ -848,7 +848,7 @@ describe('googleAuth', function() { // * Environment variable is set up to point to private.json // * Well-known file is set up to point to private2.json // * Running on GCE is set to true. - var auth = new googleAuth(); + var auth = new GoogleAuth(); insertEnvironmentVariableIntoAuth(auth, 'GOOGLE_APPLICATION_CREDENTIALS', './test/fixtures/private.json'); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); @@ -880,7 +880,7 @@ describe('googleAuth', function() { // * Environment variable is not set. // * Well-known file is set up to point to private2.json // * Running on GCE is set to true. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -907,7 +907,7 @@ describe('googleAuth', function() { // * Environment variable is not set. // * Well-known file is not set. // * Running on GCE is set to true. - var auth = new googleAuth(); + var auth = new GoogleAuth(); blockGoogleApplicationCredentialEnvironmentVariable(auth); insertEnvironmentVariableIntoAuth(auth, 'APPDATA', 'foo'); auth._pathJoin = pathJoin; @@ -929,7 +929,7 @@ describe('googleAuth', function() { describe('._checkIsGCE', function () { it('should set the _isGCE flag when running on GCE', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); // Mock the transport layer to return the correct header indicating that // we're running on GCE. @@ -950,7 +950,7 @@ describe('googleAuth', function() { }); it('should not set the _isGCE flag when not running on GCE', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); // Mock the transport layer to indicate that we're not running on GCE. auth.transporter = new MockTransporter(false); @@ -970,7 +970,7 @@ describe('googleAuth', function() { }); it('Does not execute the second time when running on GCE', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); // Mock the transport layer to indicate that we're not running on GCE. auth.transporter = new MockTransporter(true); @@ -1001,7 +1001,7 @@ describe('googleAuth', function() { }); it('Does not execute the second time when not running on GCE', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); // Mock the transport layer to indicate that we're not running on GCE. auth.transporter = new MockTransporter(false); @@ -1031,7 +1031,7 @@ describe('googleAuth', function() { }); it('Returns false on transport error', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); // Mock the transport layer to indicate that we're not running on GCE, but also to // throw an error. diff --git a/test/test.iam.js b/test/test.iam.js index 9de2135..7b2e2e9 100644 --- a/test/test.iam.js +++ b/test/test.iam.js @@ -17,14 +17,14 @@ 'use strict'; var assert = require('assert'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); describe('.getRequestMetadata', function() { var test_selector = 'a-test-selector'; var test_token = 'a-test-token'; var client; beforeEach(function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); client = new auth.IAMAuth(test_selector, test_token); }); diff --git a/test/test.jwt.js b/test/test.jwt.js index 9b803b8..9444f7d 100644 --- a/test/test.jwt.js +++ b/test/test.jwt.js @@ -18,7 +18,7 @@ var assert = require('assert'); var fs = require('fs'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var jws = require('jws'); var keypair = require('keypair'); var nock = require('nock'); @@ -41,7 +41,7 @@ describe('Initial credentials', function() { it('should create a dummy refresh token string', function () { // It is important that the compute client is created with a refresh token value filled // in, or else the rest of the logic will not work. - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT(); assert.equal('jwt-placeholder', jwt.credentials.refresh_token); }); @@ -53,7 +53,7 @@ describe('JWT auth client', function() { describe('.authorize', function() { it('should get an initial access token', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -83,7 +83,7 @@ describe('JWT auth client', function() { }); it('should accept scope as string', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -109,7 +109,7 @@ describe('JWT auth client', function() { describe('when scopes are set', function() { it('can get obtain new access token', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -144,7 +144,7 @@ describe('JWT auth client', function() { describe('when scopes are set', function() { it('can obtain new access token', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -182,7 +182,7 @@ describe('JWT auth client', function() { it('gets a jwt header access token', function(done) { var keys = keypair(1024 /* bitsize of private key */); var email = 'foo@serviceaccount.com'; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', null, @@ -216,7 +216,7 @@ describe('JWT auth client', function() { describe('.request', function() { it('should refresh token if missing access token', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -241,7 +241,7 @@ describe('JWT auth client', function() { }); it('should refresh token if expired', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -273,7 +273,7 @@ describe('JWT auth client', function() { .post('/o/oauth2/token', '*') .reply(200, { access_token: 'abc123', expires_in: 10000 }); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -301,7 +301,7 @@ describe('JWT auth client', function() { .post('/o/oauth2/token', '*') .reply(200, { access_token: 'abc123', expires_in: 10000 }); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -325,7 +325,7 @@ describe('JWT auth client', function() { }); it('should return expiry_date in milliseconds', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -358,7 +358,7 @@ describe('.createScoped', function() { // set up the auth module. var auth; beforeEach(function() { - auth = new googleAuth(); + auth = new GoogleAuth(); }); it('should clone stuff', function() { @@ -457,7 +457,7 @@ describe('.createScopedRequired', function() { // set up the auth module. var auth; beforeEach(function() { - auth = new googleAuth(); + auth = new GoogleAuth(); }); it('should return true when scopes is null', function () { @@ -505,7 +505,7 @@ describe('.createScopedRequired', function() { }); it('should return false when scopes is a filled-in array', function () { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -519,7 +519,7 @@ describe('.createScopedRequired', function() { it('should return false when scopes is not an array or a string, but can be used as a string', function () { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', @@ -536,7 +536,7 @@ describe('.fromJson', function () { var jwt, json; beforeEach(function() { json = createJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); jwt = new auth.JWT(); }); @@ -618,7 +618,7 @@ describe('.fromStream', function () { // set up the jwt instance being tested. var jwt; beforeEach(function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); jwt = new auth.JWT(); }); diff --git a/test/test.jwtaccess.js b/test/test.jwtaccess.js index 354d495..08d82c0 100644 --- a/test/test.jwtaccess.js +++ b/test/test.jwtaccess.js @@ -18,7 +18,7 @@ var assert = require('assert'); var fs = require('fs'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var keypair = require('keypair'); var jws = require('jws'); @@ -40,7 +40,7 @@ describe('.getRequestMetadata', function() { var keys = keypair(1024 /* bitsize of private key */); var testUri = 'http:/example.com/my_test_service'; var email = 'foo@serviceaccount.com'; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var client = new auth.JWTAccess(email, keys['private']); var retValue = 'dummy'; @@ -63,7 +63,7 @@ describe('.getRequestMetadata', function() { describe('.createScopedRequired', function() { it('should return false', function () { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var client = new auth.JWTAccess( 'foo@serviceaccount.com', null); @@ -78,7 +78,7 @@ describe('.fromJson', function () { var json, client; beforeEach(function() { json = createJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); client = new auth.JWTAccess(); }); @@ -136,7 +136,7 @@ describe('.fromStream', function () { // set up the client instance being tested. var client; beforeEach(function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); client = new auth.JWTAccess(); }); diff --git a/test/test.oauth2.js b/test/test.oauth2.js index 71e347c..578d92a 100644 --- a/test/test.oauth2.js +++ b/test/test.oauth2.js @@ -20,7 +20,7 @@ var url = require('url'); var assert = require('assert'); var qs = require('querystring'); var fs = require('fs'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var crypto = require('crypto'); var nock = require('nock'); var AuthClient = require('../lib/auth/authclient.js'); @@ -43,7 +43,7 @@ describe('OAuth2 client', function() { response_type: 'code token' }; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl(opts); var parsed = url.parse(generated); @@ -71,7 +71,7 @@ describe('OAuth2 client', function() { response_type: 'code token' }; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl(opts); var parsed = url.parse(generated); @@ -83,7 +83,7 @@ describe('OAuth2 client', function() { it('should set response_type param to code if none is given while' + 'generating the consent page url', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl(); var parsed = url.parse(generated); @@ -96,7 +96,7 @@ describe('OAuth2 client', function() { // jason: keep /* it('should return err no access or refresh token is set before making a request', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new googleapis.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); new googleapis.GoogleApis() .urlshortener('v1').url.get({ shortUrl: '123', auth: oauth2client }, function(err, result) { @@ -166,7 +166,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var login = oauth2client.verifySignedJwtWithCerts(data, {keyid: publicKey}, 'testaudience'); @@ -210,7 +210,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -258,7 +258,7 @@ describe('OAuth2 client', function() { //Originally: data += '.'+signature; data += signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -309,7 +309,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -360,7 +360,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -404,7 +404,7 @@ describe('OAuth2 client', function() { '.' + new Buffer(idToken).toString('base64') + '.' + 'broken-signature'; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -452,7 +452,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -502,7 +502,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -552,7 +552,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -603,7 +603,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.verifySignedJwtWithCerts( data, @@ -652,7 +652,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -704,7 +704,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -754,7 +754,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); assert.throws( function() { @@ -805,7 +805,7 @@ describe('OAuth2 client', function() { data += '.' + signature; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.verifySignedJwtWithCerts( data, @@ -821,7 +821,7 @@ describe('OAuth2 client', function() { var scope = nock('https://www.googleapis.com') .get('/oauth2/v1/certs') .replyWithFile(200, __dirname + '/fixtures/oauthcerts.json'); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.getFederatedSignonCerts(function(err, certs) { assert.equal(err, null); @@ -842,7 +842,7 @@ describe('OAuth2 client', function() { .get('/oauth2/v1/certs') .once() .replyWithFile(200, __dirname + '/fixtures/oauthcerts.json'); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.getFederatedSignonCerts(function(err, certs) { assert.equal(err, null); @@ -859,7 +859,7 @@ describe('OAuth2 client', function() { }); it('should set redirect_uri if not provided in options', function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl({}); var parsed = url.parse(generated); @@ -868,7 +868,7 @@ describe('OAuth2 client', function() { }); it('should set client_id if not provided in options', function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl({}); var parsed = url.parse(generated); @@ -877,7 +877,7 @@ describe('OAuth2 client', function() { }); it('should override redirect_uri if provided in options', function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl({ redirect_uri: 'overridden' }); var parsed = url.parse(generated); @@ -886,7 +886,7 @@ describe('OAuth2 client', function() { }); it('should override client_id if provided in options', function() { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); var generated = oauth2client.generateAuthUrl({ client_id: 'client_override' }); var parsed = url.parse(generated); @@ -895,7 +895,7 @@ describe('OAuth2 client', function() { }); it('should return error in callback on request', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.request({}, function(err, result) { assert.equal(err.message, 'No access or refresh token is set.'); @@ -905,7 +905,7 @@ describe('OAuth2 client', function() { }); it('should return error in callback on refreshAccessToken', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.refreshAccessToken(function(err, result) { assert.equal(err.message, 'No refresh token is set.'); @@ -996,7 +996,7 @@ describe('OAuth2 client', function() { var scope = nock('https://accounts.google.com') .get('/o/oauth2/revoke?token=abc') .reply(200, { success: true }); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.credentials = { access_token: 'abc', refresh_token: 'abc' }; oauth2client.revokeCredentials(function(err, result) { @@ -1009,7 +1009,7 @@ describe('OAuth2 client', function() { }); it('should clear credentials and return error if no access token to revoke', function(done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.credentials = { refresh_token: 'abc' }; oauth2client.revokeCredentials(function(err, result) { @@ -1027,7 +1027,7 @@ describe('OAuth2 client', function() { var scope = nock('https://accounts.google.com') .post('/o/oauth2/token') .reply(200, { access_token: 'abc', refresh_token: '123', expires_in: 10 }); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var oauth2client = new auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); oauth2client.getToken('code here', function(err, tokens) { assert(tokens.expiry_date >= now + (10 * 1000)); diff --git a/test/test.refresh.js b/test/test.refresh.js index 58a4907..569a50a 100644 --- a/test/test.refresh.js +++ b/test/test.refresh.js @@ -17,7 +17,7 @@ 'use strict'; var assert = require('assert'); -var googleAuth = require('../lib/auth/googleauth.js'); +var GoogleAuth = require('../lib/auth/googleauth.js'); var nock = require('nock'); var fs = require('fs'); @@ -40,7 +40,7 @@ describe('Refresh Token auth client', function() { describe('.fromJson', function () { it('should error on null json', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(null, function (err) { assert.equal(true, err instanceof Error); @@ -49,7 +49,7 @@ describe('.fromJson', function () { }); it('should error on empty json', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON({}, function (err) { assert.equal(true, err instanceof Error); @@ -61,7 +61,7 @@ describe('.fromJson', function () { var json = createJSON(); delete json.client_id; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -73,7 +73,7 @@ describe('.fromJson', function () { var json = createJSON(); delete json.client_secret; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -85,7 +85,7 @@ describe('.fromJson', function () { var json = createJSON(); delete json.refresh_token; - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.equal(true, err instanceof Error); @@ -95,7 +95,7 @@ describe('.fromJson', function () { it('should create UserRefreshClient with clientId_', function(done) { var json = createJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.ifError(err); @@ -106,7 +106,7 @@ describe('.fromJson', function () { it('should create UserRefreshClient with clientSecret_', function(done) { var json = createJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.ifError(err); @@ -117,7 +117,7 @@ describe('.fromJson', function () { it('should create UserRefreshClient with _refreshToken', function(done) { var json = createJSON(); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromJSON(json, function (err) { assert.ifError(err); @@ -130,7 +130,7 @@ describe('.fromJson', function () { describe('.fromStream', function () { it('should error on null stream', function (done) { - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromStream(null, function (err) { assert.equal(true, err instanceof Error); @@ -147,7 +147,7 @@ describe('.fromStream', function () { var stream = fs.createReadStream('./test/fixtures/refresh.json'); // And pass it into the fromStream method. - var auth = new googleAuth(); + var auth = new GoogleAuth(); var refresh = new auth.UserRefreshClient(); refresh.fromStream(stream, function (err) { assert.ifError(err); From 79a732948c7a9f37fea5c4d3ec12de8968f6eca1 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 1 Apr 2016 09:55:35 -0700 Subject: [PATCH 4/8] Check that pem exists before verifying it. --- lib/auth/oauth2client.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/auth/oauth2client.js b/lib/auth/oauth2client.js index e044846..782ef12 100644 --- a/lib/auth/oauth2client.js +++ b/lib/auth/oauth2client.js @@ -492,6 +492,10 @@ OAuth2Client.prototype.verifySignedJwtWithCerts = throw new Error('Can\'t parse token payload: ' + segments[1]); } + if (!certs.hasOwnProperty(envelope.kid)) { + // If this is not present, then there's no reason to attempt verification + throw new Error('No pem found for envelope: ' + JSON.stringify(envelope)); + } var pem = certs[envelope.kid]; var pemVerifier = new PemVerifier(); var verified = pemVerifier.verify(pem, signed, signature, 'base64'); From 840830873549d5e04f73f28e3669f8371e10f81c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 1 Apr 2016 11:21:52 -0700 Subject: [PATCH 5/8] Fix some lint errors --- lib/auth/oauth2client.js | 4 +++- test/test.jwt.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/auth/oauth2client.js b/lib/auth/oauth2client.js index aa7e702..4a38732 100644 --- a/lib/auth/oauth2client.js +++ b/lib/auth/oauth2client.js @@ -336,6 +336,7 @@ OAuth2Client.prototype.revokeCredentials = function(callback) { * @return {Request} Request object */ OAuth2Client.prototype.request = function(opts, callback) { + /* jshint latedef:false */ var that = this; // Callbacks will close over this to ensure that we only retry once @@ -346,7 +347,7 @@ OAuth2Client.prototype.request = function(opts, callback) { // Automatically retry 401 and 403 responses // if err is set, then getting credentials failed, and retrying won't help if (retry && !err && resp && - (resp.statusCode == 401 || resp.statusCode == 403)) { + (resp.statusCode === 401 || resp.statusCode === 403)) { /* It only makes sense to retry once, because the retry is intended to * handle expiration-related failures. If refreshing the token does not * fix the failure, then refreshing again probably won't help */ @@ -371,6 +372,7 @@ OAuth2Client.prototype.request = function(opts, callback) { return that._makeRequest(opts, postRequestCb); } }; + var unusedUri = null; return this.getRequestMetadata(unusedUri, authCb); }; diff --git a/test/test.jwt.js b/test/test.jwt.js index f17babd..dec4c31 100644 --- a/test/test.jwt.js +++ b/test/test.jwt.js @@ -268,12 +268,12 @@ describe('JWT auth client', function() { }); it('should refresh token if the server returns 403', function(done) { - var scope = nock('http://example.com') + nock('http://example.com') .log(console.log) .get('/access') .reply(403); - var auth = new googleAuth(); + var auth = new GoogleAuth(); var jwt = new auth.JWT( 'foo@serviceaccount.com', '/path/to/key.pem', From 0d7d51242f6cb5696b13ec1f26a2b7e2e181dfdf Mon Sep 17 00:00:00 2001 From: Matt Loring Date: Tue, 3 May 2016 19:45:47 +0200 Subject: [PATCH 6/8] Fix User-Agent header Prevent User-Agent header from growing with each request. Fixes #83 --- lib/transporters.js | 7 +++++-- test/test.transporters.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/transporters.js b/lib/transporters.js index e12c68b..d883f26 100644 --- a/lib/transporters.js +++ b/lib/transporters.js @@ -39,8 +39,11 @@ DefaultTransporter.prototype.USER_AGENT = DefaultTransporter.prototype.configure = function(opts) { // set transporter user agent opts.headers = opts.headers || {}; - opts.headers['User-Agent'] = opts.headers['User-Agent'] ? - opts.headers['User-Agent'] + ' ' + this.USER_AGENT : this.USER_AGENT; + if (!opts.headers['User-Agent']) { + opts.headers['User-Agent'] = this.USER_AGENT; + } else if (opts.headers['User-Agent'].indexOf(this.USER_AGENT) === -1) { + opts.headers['User-Agent'] = opts.headers['User-Agent'] + ' ' + this.USER_AGENT; + } return opts; }; diff --git a/test/test.transporters.js b/test/test.transporters.js index e72470f..b149616 100644 --- a/test/test.transporters.js +++ b/test/test.transporters.js @@ -19,6 +19,7 @@ var assert = require('assert'); var DefaultTransporter = require('../lib/transporters'); var nock = require('nock'); +var version = require('../package.json').version; nock.disableNetConnect(); @@ -42,6 +43,15 @@ describe('Transporters', function() { assert(re.test(opts.headers['User-Agent'])); }); + it('should not append default client user agent to the existing user ' + + 'agent more than once', function() { + var applicationName = 'MyTestApplication-1.0 google-api-nodejs-client/' + version; + var opts = transporter.configure({ + headers: { 'User-Agent': applicationName } + }); + assert.equal(opts.headers['User-Agent'], applicationName); + }); + it('should create a single error from multiple response errors', function(done) { var firstError = { message: 'Error 1' From 781507d8eb3f2fc3284d10e83df58b6b31cc12cc Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 10 May 2016 11:41:03 -0700 Subject: [PATCH 7/8] Prepare version 0.9.8 --- CHANGELOG.md | 16 +++++++ README.md | 116 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 90 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dff1e9..c302696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.9.8 (05/10/2016) + +### Changes + +* Update README.md ([@tbetbetbe][]) +* Check that pem exists before verifying it ([@murgatroid99][]) +* Fix User-Agent header ([@matthewloring][]) +* Fix some lint errors ([@murgatroid99][]) +* Added test for OAuth2Client#request retry, fixed implementation ([@murgatroid99][]) +* Fixed returned toString encoding of OAuth2Client.prototype.decodeBase64 method. ([@yamafaktory][]) +* Use full compute metadata DNS name ([@jonparrot][]) + ## 0.9.7 (11/06/2015) ### Changes @@ -41,3 +53,7 @@ [@ryan-devrel]: https://github.com/ryan-devrel [@stephenplusplus]: https://github.com/stephenplusplus [@tbetbetbe]: https://github.com/tbetbetbe +[@murgatroid99]: https//github.com/murgatroid99 +[@matthewloring]: https://github.com/matthewloring +[@yamafaktory]: https://github.com/yamafaktory +[@jonparrot]: https://github.com/jonparrot diff --git a/README.md b/README.md index 42f9df3..fb132e4 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,6 @@ This is Google's officially supported [node.js][node] client library for using OAuth 2.0 authorization and authentication with Google APIs. -### Alpha - -This library is in Alpha. We will make an effort to support the library, but we reserve the right to make incompatible changes when necessary. - ### Questions/problems? * Ask your development related questions on [![Ask a question on Stackoverflow][overflowimg]][stackoverflow] @@ -24,46 +20,10 @@ run the following command: $ npm install google-auth-library --save ``` -## License - -This library is licensed under Apache 2.0. Full license text is -available in [COPYING][copying]. - -## Example Usage - -``` js -var GoogleAuth = require('google-auth-library'); - -// Get the environment configured authorization -(new GoogleAuth).getApplicationDefault(function(err, authClient) { - if (err === null) { - // Inject scopes if they have not been injected by the environment - if (authClient.createScopedRequired && authClient.createScopedRequired()) { - var scopes = [ - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/compute' - ]; - authClient = authClient.createScoped(scopes); - } - - // Fetch the access token - var _ = require(lodash); - var optionalUri = null; // optionally specify the URI being authorized - var reqHeaders = {}; - authClient.getRequestMetadata(optionalUri, function(err, headers) { - if (err === null) { - // Use authorization headers - reqHeaders = _.merge(allHeaders, headers); - } - }); - } -}); -``` - ## Application Default Credentials -This library provides an implementation of application default credentials for Node.js. +This library provides an implementation of [Application Default Credentials][] for Node.js. -The Application Default Credentials provide a simple way to get authorization credentials for use +The [Application Default Credentials][] provide a simple way to get authorization credentials for use in calling Google APIs. They are best suited for cases when the call needs to have the same identity and authorization @@ -71,10 +31,81 @@ level for the application independent of the user. This is the recommended appro calls to Cloud APIs, particularly when you're building an application that uses Google Compute Engine. +#### Download your Service Account Credentials JSON file + +To use `Application Default Credentials`, You first need to download a set of +JSON credentials for your project. Go to **APIs & Auth** > **Credentials** in +the [Google Developers Console](developer console) and select +**Service account** from the **Add credentials** dropdown. + +> This file is your *only copy* of these credentials. It should never be +> committed with your source code, and should be stored securely. + +Once downloaded, store the path to this file in the +`GOOGLE_APPLICATION_CREDENTIALS` environment variable. + +#### Enable the API you want to use + +Before making your API call, you must be sure the API you're calling has been +enabled. Go to **APIs & Auth** > **APIs** in the +[Google Developers Console](developer console) and enable the APIs you'd like to +call. For the example below, you must enable the `DNS API`. + +#### Call an API + +As long as you update the environment variable below to point to *your* JSON +credentials file, and the fill in the placeholder variables from your project, +the following snippet should work. + +```js +var google = require('googleapis'); +var GoogleAuth = require('google-auth-library'); + +var authFactory = new GoogleAuth(); +var dns = google.dns('v1'); + +authFactory.getApplicationDefault(function(err, authClient) { + if (err) { + console.log('Authentication failed because of ', err); + return; + } + if (authClient.createScopedRequired && authClient.createScopedRequired()) { + var scopes = ['https://www.googleapis.com/auth/cloud-platform']; + authClient = authClient.createScoped(scopes); + } + + var request = { + // TODO: Change placeholders below to values for parameters to the 'get' method: + + // Identifies the project addressed by this request. + project: "", + // Identifies the managed zone addressed by this request. Can be the managed zone name or id. + managedZone: "", + // The identifier of the requested change, from a previous ResourceRecordSetsChangeResponse. + changeId: "", + // Auth client + auth: authClient + }; + + dns.changes.get(request, function(err, result) { + if (err) { + console.log(err); + } else { + console.log(result); + } + }); +}); +``` + ## Contributing See [CONTRIBUTING][contributing]. +## License + +This library is licensed under Apache 2.0. Full license text is +available in [COPYING][copying]. + [travisimg]: https://api.travis-ci.org/google/google-auth-library-nodejs.svg [bugs]: https://github.com/google/google-auth-library-nodejs/issues [node]: http://nodejs.org/ @@ -98,3 +129,4 @@ See [CONTRIBUTING][contributing]. [cloudplatform]: https://developers.google.com/cloud/ [coveralls]: https://coveralls.io/r/google/google-auth-library-nodejs?branch=master [coverallsimg]: https://img.shields.io/coveralls/google/google-auth-library-nodejs.svg +[Application Default Credentials]: https://developers.google.com/identity/protocols/application-default-credentials#callingnode From 3095ca28466419f5e286822d652dbfcb2885b898 Mon Sep 17 00:00:00 2001 From: Patrick Heneise Date: Wed, 1 Jun 2016 22:00:20 +0200 Subject: [PATCH 8/8] Medium severity vulnerability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Please update request: ✗ Medium severity vulnerability found on request@2.60.0 - desc: Remote Memory Exposure - info: https://snyk.io/vuln/npm:request:20160119 - from: myproject > googleapis@7.1.0 > google-auth-library@0.9.8 > request@2.60.0 Your dependencies are out of date, otherwise you would be using a newer request than request@2.60.0. https://snyk.io/vuln/npm:request:20160119 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67657ba..97de59c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "gtoken": "^1.1.0", "lodash.noop": "~3.0.0", "jws": "~3.0.0", - "request": "~2.60.0", + "request": "~2.72.0", "string-template": "~0.2.0" }, "devDependencies": {