Skip to content

Commit

Permalink
Merge pull request #823 from stephenplusplus/spp--core-google-auto-auth
Browse files Browse the repository at this point in the history
core: use google-auto-auth
  • Loading branch information
callmehiphop committed Aug 26, 2015
2 parents fb74561 + e63e36d commit 2b80071
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 495 deletions.
141 changes: 14 additions & 127 deletions lib/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

var extend = require('extend');
var GoogleAuth = require('google-auth-library');
var googleAuth = require('google-auto-auth');
var is = require('is');
var nodeutil = require('util');
var request = require('request').defaults({
Expand Down Expand Up @@ -324,109 +324,6 @@ function shouldRetryRequest(err) {

util.shouldRetryRequest = shouldRetryRequest;

/**
* Create an Auth Client from Google Auth Library, used to get an access token
* for authenticating API requests.
*
* @param {object} config - Configuration object.
* @param {object=} config.authClient - AuthClient object. If not provided,
* it will be created and cached here.
* @param {object=} config.credentials - Credentials object.
* @param {string=} config.email - Account email address, required for PEM/P12
* usage.
* @param {string=} config.keyFile - Path to a .json, .pem, or .p12 keyfile.
* @param {array} config.scopes - Array of scopes required for the API.
* @param {function} callback - The callback function.
*/
function getAuthClient(config, callback) {
if (config.authClient) {
setImmediate(function() {
callback(null, config.authClient);
});
return;
}
var googleAuth = new GoogleAuth();

if (config.keyFile) {
var authClient = new googleAuth.JWT();
authClient.keyFile = config.keyFile;
authClient.email = config.email;
authClient.scopes = config.scopes;
addScope(null, authClient);
} else if (config.credentials) {
googleAuth.fromJSON(config.credentials, addScope);
} else {
googleAuth.getApplicationDefault(addScope);
}

function addScope(err, authClient) {
if (err) {
callback(err);
return;
}

if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped(config.scopes);
}

config.authClient = authClient;
callback(null, authClient);
}
}

util.getAuthClient = getAuthClient;

/**
* Authenticate a request by extending its headers object with an access token.
*
* @param {object} config - Configuration object.
* @param {object=} config.authClient - AuthClient object. If not provided,
* it will be created and cached here.
* @param {object=} config.credentials - Credentials object.
* @param {string=} config.email - Account email address, required for PEM/P12
* usage.
* @param {string=} config.keyFile - Path to a .json, .pem, or .p12 keyfile.
* @param {array} config.scopes - Array of scopes required for the API.
* @param {object} reqOpts - HTTP request options. Its `headers` object is
* created or extended with a valid access token.
* @param {function} callback - The callback function.
*/
function authorizeRequest(config, reqOpts, callback) {
util.getAuthClient(config, function(err, authClient) {
if (err) {
// google-auth-library returns a "Could not load..." error if it can't get
// an access token. However, it's possible an API request doesn't need to
// be authenticated, e.g. when downloading a file from a public bucket. We
// consider this error a warning, and allow the request to go through
// without authorization, relying on the upstream API to return an error
// the user would find more helpful, should one occur.
if (err.message.indexOf('Could not load') === 0) {
callback(null, reqOpts);
} else {
callback(err);
}
return;
}

authClient.getAccessToken(function(err, token) {
if (err) {
callback(err);
return;
}

var authorizedReqOpts = extend(true, {}, reqOpts, {
headers: {
Authorization: 'Bearer ' + token
}
});

callback(null, authorizedReqOpts);
});
});
}

util.authorizeRequest = authorizeRequest;

/**
* Get a function for making authorized requests.
*
Expand All @@ -450,6 +347,8 @@ util.authorizeRequest = authorizeRequest;
function makeAuthorizedRequestFactory(config) {
config = config || {};

var authClient = googleAuth(config);

/**
* The returned function that will make an authorized request.
*
Expand All @@ -470,7 +369,13 @@ function makeAuthorizedRequestFactory(config) {
}

function onAuthorized(err, authorizedReqOpts) {
if (err) {
// google-auth-library returns a "Could not load..." error if it can't get
// an access token. However, it's possible an API request doesn't need to
// be authenticated, e.g. when downloading a file from a public bucket. We
// consider this error a warning, and allow the request to go through
// without authorization, relying on the upstream API to return an error
// the user would find more helpful, should one occur.
if (err && err.message.indexOf('Could not load') === -1) {
if (stream) {
stream.destroy(err);
} else {
Expand All @@ -490,38 +395,20 @@ function makeAuthorizedRequestFactory(config) {
}

if (reqConfig.customEndpoint) {
// Using a custom API override. Do not use `google-auth-library` for
// Using a custom API override. Do not use `google-auto-auth` for
// authentication. (ex: connecting to a local Datastore server)
onAuthorized(null, reqOpts);
} else {
util.authorizeRequest(reqConfig, reqOpts, onAuthorized);
authClient.authorizeRequest(reqOpts, onAuthorized);
}

if (stream) {
return stream;
}
}

makeAuthorizedRequest.getCredentials = function(callback) {
util.getAuthClient(config, function(err, authClient) {
if (err) {
callback(err);
return;
}

authClient.authorize(function(err) {
if (err) {
callback(err);
return;
}

callback(null, {
client_email: authClient.email,
private_key: authClient.key
});
});
});
};
makeAuthorizedRequest.getCredentials =
authClient.getCredentials.bind(authClient);

return makeAuthorizedRequest;
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"duplexify": "^3.2.0",
"extend": "^2.0.0",
"gce-images": "^0.1.0",
"google-auth-library": "^0.9.4",
"google-auto-auth": "^0.2.0",
"is": "^3.0.1",
"methmeth": "^1.0.0",
"mime-types": "^2.0.8",
Expand Down
Loading

0 comments on commit 2b80071

Please sign in to comment.