This commit is contained in:
GotPPay
2017-10-16 20:21:19 +02:00
parent 8a7f8794cf
commit a75ea978f9
2554 changed files with 804218 additions and 109 deletions

View File

@@ -0,0 +1,26 @@
/**
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var transporters_1 = require("../transporters");
var AuthClient = (function () {
function AuthClient() {
this.transporter = new transporters_1.DefaultTransporter();
}
return AuthClient;
}());
exports.AuthClient = AuthClient;
//# sourceMappingURL=authclient.js.map

View File

@@ -0,0 +1,120 @@
/**
* Copyright 2013 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var oauth2client_1 = require("./oauth2client");
var Compute = (function (_super) {
__extends(Compute, _super);
/**
* Google Compute Engine service account credentials.
*
* Retrieve access token from the metadata server.
* See: https://developers.google.com/compute/docs/authentication
*/
function Compute() {
var _this = _super.call(this) || this;
// Start with an expired refresh token, which will automatically be
// refreshed before the first API call is made.
_this.credentials = { expiry_date: 1, refresh_token: 'compute-placeholder' };
return _this;
}
/**
* Indicates whether the credential requires scopes to be created by calling
* createdScoped before use.
* @return {object} The cloned instance.
*/
Compute.prototype.createScopedRequired = function () {
// On compute engine, scopes are specified at the compute instance's
// creation time, and cannot be changed. For this reason, always return
// false.
return false;
};
/**
* Refreshes the access token.
* @param {object=} ignored_
* @param {function=} callback Optional callback.
*/
Compute.prototype.refreshToken = function (ignored, callback) {
var uri = this._opts.tokenUrl || Compute._GOOGLE_OAUTH2_TOKEN_URL;
// request for new token
return this.transporter.request({ method: 'GET', uri: uri, json: true }, function (err, body, response) {
var token = body;
if (!err && token && token.expires_in) {
token.expiry_date =
((new Date()).getTime() + (token.expires_in * 1000));
delete token.expires_in;
}
if (callback) {
callback(err, token, response);
}
});
};
/**
* Inserts a helpful error message guiding the user toward fixing common auth
* issues.
* @param {object} err Error result.
* @param {object} result The result.
* @param {object} response The HTTP response.
* @param {Function} callback The callback.
*/
Compute.prototype.postRequest = function (err, result, response, callback) {
if (response && response.statusCode) {
var helpfulMessage = null;
if (response.statusCode === 403) {
helpfulMessage =
'A Forbidden error was returned while attempting to retrieve an access ' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have the correct permission scopes specified.';
}
else if (response.statusCode === 404) {
helpfulMessage =
'A Not Found error was returned while attempting to retrieve an access' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have any permission scopes specified.';
}
if (helpfulMessage) {
if (err && err.message) {
helpfulMessage += ' ' + err.message;
}
if (err) {
err.message = helpfulMessage;
}
else {
err = new Error(helpfulMessage);
err.code = response.statusCode;
}
}
}
callback(err, result, response);
};
return Compute;
}(oauth2client_1.OAuth2Client));
/**
* Google Compute Engine metadata server token endpoint.
*/
Compute._GOOGLE_OAUTH2_TOKEN_URL = 'http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token';
exports.Compute = Compute;
//# sourceMappingURL=computeclient.js.map

View File

@@ -0,0 +1,18 @@
/**
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=credentials.js.map

View File

@@ -0,0 +1,579 @@
/**
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var child_process_1 = require("child_process");
var fs = require("fs");
var os = require("os");
var path = require("path");
var util = require("util");
var transporters_1 = require("../transporters");
var computeclient_1 = require("./computeclient");
var iam_1 = require("./iam");
var jwtaccess_1 = require("./jwtaccess");
var jwtclient_1 = require("./jwtclient");
var oauth2client_1 = require("./oauth2client");
var refreshclient_1 = require("./refreshclient");
var GoogleAuth = (function () {
function GoogleAuth() {
/**
* Caches a value indicating whether the auth layer is running on Google
* Compute Engine.
* @private
*/
this._isGCE = undefined;
this.cachedCredential = null;
this.JWTClient = jwtclient_1.JWT;
this.ComputeClient = computeclient_1.Compute;
/**
* Convenience field mapping in the IAM credential type.
*/
this.IAMAuth = iam_1.IAMAuth;
/**
* Convenience field mapping in the Compute credential type.
*/
this.Compute = computeclient_1.Compute;
/**
* Convenience field mapping in the JWT credential type.
*/
this.JWT = jwtclient_1.JWT;
/**
* Convenience field mapping in the JWT Access credential type.
*/
this.JWTAccess = jwtaccess_1.JWTAccess;
/**
* Convenience field mapping in the OAuth2 credential type.
*/
this.OAuth2 = oauth2client_1.OAuth2Client;
/**
* Convenience field mapping to the UserRefreshClient credential type.
*/
this.UserRefreshClient = refreshclient_1.UserRefreshClient;
}
Object.defineProperty(GoogleAuth.prototype, "isGCE", {
// Note: this properly is only public to satisify unit tests.
// https://github.com/Microsoft/TypeScript/issues/5228
get: function () {
return this._isGCE;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GoogleAuth.prototype, "cachedProjectId", {
// Note: this properly is only public to satisify unit tests.
// https://github.com/Microsoft/TypeScript/issues/5228
set: function (projectId) {
this._cachedProjectId = projectId;
},
enumerable: true,
configurable: true
});
/**
* Obtains the default project ID for the application..
* @param {function=} callback Optional callback.
*/
GoogleAuth.prototype.getDefaultProjectId = function (callback) {
// In implicit case, supports three environments. In order of precedence,
// the implicit environments are:
//
// * GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variable
// * GOOGLE_APPLICATION_CREDENTIALS JSON file
// * Get default service project from
// ``$ gcloud beta auth application-default login``
// * Google App Engine application ID (Not implemented yet)
// * Google Compute Engine project ID (from metadata server) (Not
// implemented yet)
var _this = this;
if (this._cachedProjectId) {
setImmediate(function () {
_this.callback(callback, null, _this._cachedProjectId);
});
}
else {
var my_callback_1 = function (err, projectId) {
if (!err && projectId) {
_this._cachedProjectId = projectId;
}
setImmediate(function () {
_this.callback(callback, err, projectId);
});
};
// environment variable
if (this._getProductionProjectId(my_callback_1)) {
return;
}
// json file
this._getFileProjectId(function (err, projectId) {
if (err || projectId) {
my_callback_1(err, projectId);
return;
}
// Google Cloud SDK default project id
_this._getDefaultServiceProjectId(function (err2, projectId2) {
if (err2 || projectId2) {
my_callback_1(err2, projectId2);
return;
}
// Get project ID from Compute Engine metadata server
_this._getGCEProjectId(my_callback_1);
});
});
}
};
/**
* Run the Google Cloud SDK command that prints the default project ID
* @param {function} _callback Callback.
* @api private
*/
GoogleAuth.prototype._getSDKDefaultProjectId = function (_callback) {
child_process_1.exec('gcloud -q config list core/project --format=json', _callback);
};
/**
* Obtains the default service-level credentials for the application..
* @param {function=} callback Optional callback.
*/
GoogleAuth.prototype.getApplicationDefault = function (callback) {
var _this = this;
// If we've already got a cached credential, just return it.
if (this.cachedCredential) {
setImmediate(function () {
_this.callback(callback, null, _this.cachedCredential, _this._cachedProjectId);
});
}
else {
// Inject our own callback routine, which will cache the credential once
// it's been created. It also allows us to ensure that the ultimate
// callback is always async.
var my_callback_2 = function (err, result) {
if (!err && result) {
_this.cachedCredential = result;
_this.getDefaultProjectId(function (err2, projectId) {
setImmediate(function () {
// Ignore default project error
_this.callback(callback, null, result, projectId);
});
});
}
else {
setImmediate(function () {
_this.callback(callback, err, result);
});
}
};
// Check for the existence of a local environment variable pointing to the
// location of the credential file. This is typically used in local
// developer scenarios.
if (this._tryGetApplicationCredentialsFromEnvironmentVariable(my_callback_2)) {
return;
}
// Look in the well-known credential file location.
if (this._tryGetApplicationCredentialsFromWellKnownFile(my_callback_2)) {
return;
}
// Determine if we're running on GCE.
this._checkIsGCE(function (gce) {
if (gce) {
// For GCE, just return a default ComputeClient. It will take care of
// the rest.
my_callback_2(null, new _this.ComputeClient());
}
else {
// We failed to find the default credentials. Bail out with an error.
my_callback_2(new Error('Could not load the default credentials. Browse to ' +
'https://developers.google.com/accounts/docs/application-default-credentials for ' +
'more information.'));
}
});
}
};
/**
* Determines whether the auth layer is running on Google Compute Engine.
* @param {function=} callback The callback.
* @api private
*/
GoogleAuth.prototype._checkIsGCE = function (callback) {
var _this = this;
if (this._isGCE !== undefined) {
callback(this._isGCE);
}
else {
if (!this.transporter) {
this.transporter = new transporters_1.DefaultTransporter();
}
this.transporter.request({ method: 'GET', uri: 'http://metadata.google.internal', json: true }, function (err, body, res) {
if (!err && res && res.headers) {
_this._isGCE = res.headers['metadata-flavor'] === 'Google';
}
callback(_this._isGCE);
});
}
};
/**
* Attempts to load default credentials from the environment variable path..
* @param {function=} callback Optional callback.
* @return {boolean} Returns true if the callback has been executed; false otherwise.
* @api private
*/
GoogleAuth.prototype._tryGetApplicationCredentialsFromEnvironmentVariable = function (callback) {
var _this = this;
var credentialsPath = this._getEnv('GOOGLE_APPLICATION_CREDENTIALS');
if (!credentialsPath || credentialsPath.length === 0) {
return false;
}
this._getApplicationCredentialsFromFilePath(credentialsPath, function (err, result) {
var wrappedError = null;
if (err) {
wrappedError = _this.createError('Unable to read the credential file specified by the GOOGLE_APPLICATION_CREDENTIALS ' +
'environment variable.', err);
}
_this.callback(callback, wrappedError, result);
});
return true;
};
/**
* Attempts to load default credentials from a well-known file location
* @param {function=} callback Optional callback.
* @return {boolean} Returns true if the callback has been executed; false otherwise.
* @api private
*/
GoogleAuth.prototype._tryGetApplicationCredentialsFromWellKnownFile = function (callback) {
// First, figure out the location of the file, depending upon the OS type.
var location = null;
if (this._isWindows()) {
// Windows
location = this._getEnv('APPDATA');
}
else {
// Linux or Mac
var home = this._getEnv('HOME');
if (home) {
location = this._pathJoin(home, '.config');
}
}
// If we found the root path, expand it.
if (location) {
location = this._pathJoin(location, 'gcloud');
location =
this._pathJoin(location, 'application_default_credentials.json');
location = this._mockWellKnownFilePath(location);
// Check whether the file exists.
if (!this._fileExists(location)) {
location = null;
}
}
// The file does not exist.
if (!location) {
return false;
}
// The file seems to exist. Try to use it.
this._getApplicationCredentialsFromFilePath(location, callback);
return true;
};
/**
* Attempts to load default credentials from a file at the given path..
* @param {string=} filePath The path to the file to read.
* @param {function=} callback Optional callback.
* @api private
*/
GoogleAuth.prototype._getApplicationCredentialsFromFilePath = function (filePath, callback) {
var error = null;
// Make sure the path looks like a string.
if (!filePath || filePath.length === 0) {
error = new Error('The file path is invalid.');
}
// Make sure there is a file at the path. lstatSync will throw if there is
// nothing there.
if (!error) {
try {
// Resolve path to actual file in case of symlink. Expect a thrown error
// if not resolvable.
filePath = fs.realpathSync(filePath);
if (!fs.lstatSync(filePath).isFile()) {
throw new Error();
}
}
catch (err) {
error = this.createError(util.format('The file at %s does not exist, or it is not a file.', filePath), err);
}
}
// Now open a read stream on the file, and parse it.
if (!error) {
try {
var stream_1 = this._createReadStream(filePath);
this.fromStream(stream_1, callback);
}
catch (err) {
error = this.createError(util.format('Unable to read the file at %s.', filePath), err);
}
}
if (error) {
this.callback(callback, error);
}
};
/**
* Create a credentials instance using the given input options.
* @param {object=} json The input object.
* @param {function=} callback Optional callback.
*/
GoogleAuth.prototype.fromJSON = function (json, callback) {
var _this = this;
var client = null;
if (!json) {
this.callback(callback, new Error('Must pass in a JSON object containing the Google auth settings.'));
return;
}
if (json.type === 'authorized_user') {
client = new refreshclient_1.UserRefreshClient();
}
else {
client = new jwtclient_1.JWT();
}
client.fromJSON(json, function (err) {
if (err) {
_this.callback(callback, err);
}
else {
_this.callback(callback, null, client);
}
});
};
/**
* Create a credentials instance using the given input stream.
* @param {object=} stream The input stream.
* @param {function=} callback Optional callback.
*/
GoogleAuth.prototype.fromStream = function (stream, callback) {
var _this = this;
if (!stream) {
setImmediate(function () {
_this.callback(callback, new Error('Must pass in a stream containing the Google auth settings.'));
});
return;
}
var s = '';
stream.setEncoding('utf8');
stream.on('data', function (chunk) {
s += chunk;
});
stream.on('end', function () {
try {
var data = JSON.parse(s);
_this.fromJSON(data, callback);
}
catch (err) {
_this.callback(callback, err);
}
});
};
/**
* Create a credentials instance using the given API key string.
* @param {string} - The API key string
* @param {function=} - Optional callback function
*/
GoogleAuth.prototype.fromAPIKey = function (apiKey, callback) {
var _this = this;
var client = new this.JWTClient();
client.fromAPIKey(apiKey, function (err) {
if (err) {
_this.callback(callback, err);
}
else {
_this.callback(callback, null, client);
}
});
};
/**
* Determines whether the current operating system is Windows.
* @api private
*/
GoogleAuth.prototype._isWindows = function () {
var sys = this._osPlatform();
if (sys && sys.length >= 3) {
if (sys.substring(0, 3).toLowerCase() === 'win') {
return true;
}
}
return false;
};
/**
* Creates a file stream. Allows mocking.
* @api private
*/
GoogleAuth.prototype._createReadStream = function (filePath) {
return fs.createReadStream(filePath);
};
/**
* Gets the value of the environment variable with the given name. Allows
* mocking.
* @api private
*/
GoogleAuth.prototype._getEnv = function (name) {
return process.env[name];
};
/**
* Gets the current operating system platform. Allows mocking.
* @api private
*/
GoogleAuth.prototype._osPlatform = function () {
return os.platform();
};
/**
* Determines whether a file exists. Allows mocking.
* @api private
*/
GoogleAuth.prototype._fileExists = function (filePath) {
return fs.existsSync(filePath);
};
/**
* Joins two parts of a path. Allows mocking.
* @api private
*/
GoogleAuth.prototype._pathJoin = function (item1, item2) {
return path.join(item1, item2);
};
/**
* Allows mocking of the path to a well-known file.
* @api private
*/
GoogleAuth.prototype._mockWellKnownFilePath = function (filePath) {
return filePath;
};
// Executes the given callback if it is not null.
GoogleAuth.prototype.callback = function (c, err) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
if (c) {
return c.apply(null, Array.prototype.slice.call(arguments, 1));
}
};
// Creates an Error containing the given message, and includes the message
// from the optional err passed in.
GoogleAuth.prototype.createError = function (message, err) {
var s = message || '';
if (err) {
var errorMessage = String(err);
if (errorMessage && errorMessage.length > 0) {
if (s.length > 0) {
s += ' ';
}
s += errorMessage;
}
}
return Error(s);
};
/**
* Loads the default project of the Google Cloud SDK.
* @param {function} _callback Callback.
* @api private
*/
GoogleAuth.prototype._getDefaultServiceProjectId = function (_callback) {
var _this = this;
this._getSDKDefaultProjectId(function (err, stdout) {
var projectId = null;
if (!err && stdout) {
try {
projectId = JSON.parse(stdout).core.project;
}
catch (err) {
projectId = null;
}
}
// Ignore any errors
_this.callback(_callback, null, projectId);
});
};
/**
* Loads the project id from environment variables.
* @param {function} _callback Callback.
* @api private
*/
GoogleAuth.prototype._getProductionProjectId = function (_callback) {
var _this = this;
var projectId = this._getEnv('GCLOUD_PROJECT') || this._getEnv('GOOGLE_CLOUD_PROJECT');
if (projectId) {
setImmediate(function () {
_this.callback(_callback, null, projectId);
});
}
return projectId;
};
/**
* Loads the project id from the GOOGLE_APPLICATION_CREDENTIALS json file.
* @param {function} _callback Callback.
* @api private
*/
GoogleAuth.prototype._getFileProjectId = function (_callback) {
var _this = this;
if (this.cachedCredential) {
// Try to read the project ID from the cached credentials file
setImmediate(function () {
_this.callback(_callback, null, _this.cachedCredential.projectId);
});
return;
}
// Try to load a credentials file and read its project ID
var pathExists = this._tryGetApplicationCredentialsFromEnvironmentVariable(function (err, result) {
if (!err && result) {
_this.callback(_callback, null, result.projectId);
return;
}
_this.callback(_callback, err);
});
if (!pathExists) {
this.callback(_callback, null);
}
};
/**
* Gets the Compute Engine project ID if it can be inferred.
* Uses 169.254.169.254 for the metadata server to avoid request
* latency from DNS lookup.
* See https://cloud.google.com/compute/docs/metadata#metadataserver
* for information about this IP address. (This IP is also used for
* Amazon EC2 instances, so the metadata flavor is crucial.)
* See https://github.com/google/oauth2client/issues/93 for context about
* DNS latency.
*
* @param {function} _callback Callback.
* @api private
*/
GoogleAuth.prototype._getGCEProjectId = function (_callback) {
var _this = this;
if (!this.transporter) {
this.transporter = new transporters_1.DefaultTransporter();
}
this.transporter.request({
method: 'GET',
uri: 'http://169.254.169.254/computeMetadata/v1/project/project-id',
headers: { 'Metadata-Flavor': 'Google' }
}, function (err, body, res) {
if (err || !res || res.statusCode !== 200 || !body) {
_this.callback(_callback);
return;
}
// Ignore any errors
_this.callback(_callback, null, body);
});
};
return GoogleAuth;
}());
/**
* Export DefaultTransporter as a static property of the class.
*/
GoogleAuth.DefaultTransporter = transporters_1.DefaultTransporter;
exports.GoogleAuth = GoogleAuth;
//# sourceMappingURL=googleauth.js.map

View File

@@ -0,0 +1,58 @@
/**
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var IAMAuth = (function () {
/**
* IAM credentials.
*
* @param {string=} selector the iam authority selector
* @param {string=} token the token
* @constructor
*/
function IAMAuth(selector, token) {
this.selector = selector;
this.token = token;
this.selector = selector;
this.token = token;
}
/**
* Indicates whether the credential requires scopes to be created by calling
* createdScoped before use.
*
* @return {boolean} always false
*/
IAMAuth.prototype.createScopedRequired = function () {
// IAM authorization does not use scopes.
return false;
};
/**
* Pass the selector and token to the metadataFn callback.
*
* @param {string} unused_uri is required of the credentials interface
* @param {function} metadataFn a callback invoked with object
* containing request metadata.
*/
IAMAuth.prototype.getRequestMetadata = function (unused_uri, metadataFn) {
metadataFn(null, {
'x-goog-iam-authority-selector': this.selector,
'x-goog-iam-authorization-token': this.token
});
};
return IAMAuth;
}());
exports.IAMAuth = IAMAuth;
//# sourceMappingURL=iam.js.map

View File

@@ -0,0 +1,148 @@
/**
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var jws = require('jws');
var noop = Function.prototype;
var JWTAccess = (function () {
/**
* JWTAccess service account credentials.
*
* Create a new access token by using the credential to create a new JWT token
* that's recognized as the access token.
*
* @param {string=} email the service account email address.
* @param {string=} key the private key that will be used to sign the token.
* @constructor
*/
function JWTAccess(email, key) {
this.email = email;
this.key = key;
}
/**
* Indicates whether the credential requires scopes to be created by calling
* createdScoped before use.
*
* @return {boolean} always false
*/
JWTAccess.prototype.createScopedRequired = function () {
// JWT Header authentication does not use scopes.
return false;
};
/**
* Get a non-expired access token, after refreshing if necessary
*
* @param {string} authURI the URI being authorized
* @param {function} metadataCb a callback invoked with the jwt
* request metadata.
*/
JWTAccess.prototype.getRequestMetadata = function (authURI, metadataCb) {
var iat = Math.floor(new Date().getTime() / 1000);
var exp = iat + 3600; // 3600 seconds = 1 hour
// The payload used for signed JWT headers has:
// iss == sub == <client email>
// aud == <the authorization uri>
var payload = { iss: this.email, sub: this.email, aud: authURI, exp: exp, iat: iat };
var assertion = {
header: { alg: 'RS256', typ: 'JWT' },
payload: payload,
secret: this.key
};
// Sign the jwt and invoke metadataCb with it.
return this._signJWT(assertion, function (err, signedJWT) {
if (!err) {
return metadataCb(null, { Authorization: 'Bearer ' + signedJWT });
}
else {
return metadataCb(err, null);
}
});
};
/**
* Create a JWTAccess credentials instance using the given input options.
* @param {object=} json The input object.
* @param {function=} callback Optional callback.
*/
JWTAccess.prototype.fromJSON = function (json, callback) {
var done = callback || noop;
if (!json) {
done(new Error('Must pass in a JSON object containing the service account auth settings.'));
return;
}
if (!json.client_email) {
done(new Error('The incoming JSON object does not contain a client_email field'));
return;
}
if (!json.private_key) {
done(new Error('The incoming JSON object does not contain a private_key field'));
return;
}
// Extract the relevant information from the json key file.
this.email = json.client_email;
this.key = json.private_key;
this.projectId = json.project_id;
done();
};
/**
* Create a JWTAccess credentials instance using the given input stream.
* @param {object=} stream The input stream.
* @param {function=} callback Optional callback.
*/
JWTAccess.prototype.fromStream = function (stream, callback) {
var _this = this;
var done = callback || noop;
if (!stream) {
setImmediate(function () {
done(new Error('Must pass in a stream containing the service account auth settings.'));
});
return;
}
var s = '';
stream.setEncoding('utf8');
stream.on('data', function (chunk) {
s += chunk;
});
stream.on('end', function () {
try {
var data = JSON.parse(s);
_this.fromJSON(data, callback);
}
catch (err) {
done(err);
}
});
};
/**
* Sign the JWT object, returning any errors in the callback.
*
* signedJwtFn is a callback function(err, signedJWT); it is called with an
* error if there is an exception during signing.
*
* @param {object} assertion The assertion to sign
* @param {Function} signedJwtFn fn(err, signedJWT)
*/
JWTAccess.prototype._signJWT = function (assertion, signedJwtFn) {
try {
return signedJwtFn(null, jws.sign(assertion));
}
catch (err) {
return signedJwtFn(err);
}
};
return JWTAccess;
}());
exports.JWTAccess = JWTAccess;
//# sourceMappingURL=jwtaccess.js.map

View File

@@ -0,0 +1,234 @@
/**
* Copyright 2013 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var gToken = require('gtoken');
var jwtaccess_1 = require("./jwtaccess");
var oauth2client_1 = require("./oauth2client");
var isString = require('lodash.isstring');
var noop = Function.prototype;
var JWT = (function (_super) {
__extends(JWT, _super);
/**
* JWT service account credentials.
*
* Retrieve access token using gtoken.
*
* @param {string=} email service account email address.
* @param {string=} keyFile path to private key file.
* @param {string=} key value of key
* @param {(string|array)=} scopes list of requested scopes or a single scope.
* @param {string=} subject impersonated account's email address.
* @constructor
*/
function JWT(email, keyFile, key, scopes, subject) {
var _this = _super.call(this) || this;
_this.email = email;
_this.keyFile = keyFile;
_this.key = key;
_this.scopes = scopes;
_this.subject = subject;
_this.gToken = gToken;
_this.credentials = { refresh_token: 'jwt-placeholder', expiry_date: 1 };
return _this;
}
/**
* Creates a copy of the credential with the specified scopes.
* @param {(string|array)=} scopes List of requested scopes or a single scope.
* @return {object} The cloned instance.
*/
JWT.prototype.createScoped = function (scopes) {
return new JWT(this.email, this.keyFile, this.key, scopes, this.subject);
};
/**
* Obtains the metadata to be sent with the request.
*
* @param {string} opt_uri the URI being authorized.
* @param {function} metadataCb
*/
JWT.prototype.getRequestMetadata = function (opt_uri, metadataCb) {
if (this.createScopedRequired() && opt_uri) {
// no scopes have been set, but a uri has been provided. Use JWTAccess
// credentials.
var alt = new jwtaccess_1.JWTAccess(this.email, this.key);
return alt.getRequestMetadata(opt_uri, metadataCb);
}
else {
return _super.prototype.getRequestMetadata.call(this, opt_uri, metadataCb);
}
};
/**
* Indicates whether the credential requires scopes to be created by calling
* createdScoped before use.
* @return {boolean} false if createScoped does not need to be called.
*/
JWT.prototype.createScopedRequired = function () {
// If scopes is null, always return true.
if (this.scopes) {
// For arrays, check the array length.
if (this.scopes instanceof Array) {
return this.scopes.length === 0;
}
// For others, convert to a string and check the length.
return String(this.scopes).length === 0;
}
return true;
};
/**
* Get the initial access token using gToken.
* @param {function=} callback Optional callback.
*/
JWT.prototype.authorize = function (callback) {
var _this = this;
var done = callback || noop;
this.refreshToken(null, function (err, result) {
if (!err) {
_this.credentials = result;
_this.credentials.refresh_token = 'jwt-placeholder';
_this.key = _this.gtoken.key;
_this.email = _this.gtoken.iss;
}
done(err, result);
});
};
/**
* Refreshes the access token.
* @param {object=} ignored_
* @param {function=} callback Optional callback.
* @private
*/
JWT.prototype.refreshToken = function (ignored_, callback) {
var done = callback || noop;
return this._createGToken(function (err, gToken) {
if (err) {
return done(err);
}
else {
return gToken.getToken(function (err2, token) {
return done(err2, {
access_token: token,
token_type: 'Bearer',
expiry_date: gToken.expires_at
});
});
}
});
};
/**
* Create a JWT credentials instance using the given input options.
* @param {object=} json The input object.
* @param {function=} callback Optional callback.
*/
JWT.prototype.fromJSON = function (json, callback) {
var done = callback || noop;
if (!json) {
done(new Error('Must pass in a JSON object containing the service account auth settings.'));
return;
}
if (!json.client_email) {
done(new Error('The incoming JSON object does not contain a client_email field'));
return;
}
if (!json.private_key) {
done(new Error('The incoming JSON object does not contain a private_key field'));
return;
}
// Extract the relevant information from the json key file.
this.email = json.client_email;
this.key = json.private_key;
this.projectId = json.project_id;
done();
};
/**
* Create a JWT credentials instance using the given input stream.
* @param {object=} stream The input stream.
* @param {function=} callback Optional callback.
*/
JWT.prototype.fromStream = function (stream, callback) {
var _this = this;
var done = callback || noop;
if (!stream) {
setImmediate(function () {
done(new Error('Must pass in a stream containing the service account auth settings.'));
});
return;
}
var s = '';
stream.setEncoding('utf8');
stream.on('data', function (chunk) {
s += chunk;
});
stream.on('end', function () {
try {
var data = JSON.parse(s);
_this.fromJSON(data, callback);
}
catch (err) {
done(err);
}
});
};
/**
* Creates a JWT credentials instance using an API Key for authentication.
* @param {string} apiKey - the API Key in string form.
* @param {function=} callback - Optional callback to be invoked after
* initialization.
*/
JWT.prototype.fromAPIKey = function (apiKey, callback) {
var done = callback || noop;
if (!isString(apiKey)) {
setImmediate(function () {
done(new Error('Must provide an API Key string.'));
});
return;
}
this.apiKey = apiKey;
done(null);
};
/**
* Creates the gToken instance if it has not been created already.
* @param {function=} callback Callback.
* @private
*/
JWT.prototype._createGToken = function (callback) {
if (this.gtoken) {
return callback(null, this.gtoken);
}
else {
this.gtoken = this.gToken({
iss: this.email,
sub: this.subject,
scope: this.scopes,
keyFile: this.keyFile,
key: this.key
});
return callback(null, this.gtoken);
}
};
return JWT;
}(oauth2client_1.OAuth2Client));
exports.JWT = JWT;
//# sourceMappingURL=jwtclient.js.map

View File

@@ -0,0 +1,61 @@
/**
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var LoginTicket = (function () {
/**
* Create a simple class to extract user ID from an ID Token
*
* @param {string} env Envelope of the jwt
* @param {string} pay Payload of the jwt
* @constructor
*/
function LoginTicket(env, pay) {
this._envelope = env;
this._payload = pay;
}
LoginTicket.prototype.getEnvelope = function () {
return this._envelope;
};
LoginTicket.prototype.getPayload = function () {
return this._payload;
};
/**
* Create a simple class to extract user ID from an ID Token
*
* @return {string} The user ID
*/
LoginTicket.prototype.getUserId = function () {
var payload = this.getPayload();
if (payload && payload[LoginTicket.USER_ATTR]) {
return payload[LoginTicket.USER_ATTR];
}
return null;
};
/**
* Returns attributes from the login ticket. This can contain
* various information about the user session.
*
* @return {Object} The envelope and payload
*/
LoginTicket.prototype.getAttributes = function () {
return { envelope: this.getEnvelope(), payload: this.getPayload() };
};
return LoginTicket;
}());
LoginTicket.USER_ATTR = 'sub';
exports.LoginTicket = LoginTicket;
//# sourceMappingURL=loginticket.js.map

View File

@@ -0,0 +1,544 @@
/**
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var querystring = require("querystring");
var pemverifier_1 = require("./../pemverifier");
var transporters_1 = require("./../transporters");
var authclient_1 = require("./authclient");
var loginticket_1 = require("./loginticket");
var merge = require('lodash.merge');
var noop = Function.prototype;
var OAuth2Client = (function (_super) {
__extends(OAuth2Client, _super);
/**
* Handles OAuth2 flow for Google APIs.
*
* @param {string=} clientId The authentication client ID.
* @param {string=} clientSecret The authentication client secret.
* @param {string=} redirectUri The URI to redirect to after completing the auth request.
* @param {Object=} opt_opts optional options for overriding the given parameters.
* @constructor
*/
function OAuth2Client(clientId, clientSecret, redirectUri, opt_opts) {
var _this = _super.call(this) || this;
_this._certificateCache = null;
_this._certificateExpiry = null;
_this._clientId = clientId;
_this._clientSecret = clientSecret;
_this._redirectUri = redirectUri;
_this._opts = opt_opts || {};
_this.credentials = {};
return _this;
}
/**
* Generates URL for consent page landing.
* @param {object=} opt_opts Options.
* @return {string} URL to consent page.
*/
OAuth2Client.prototype.generateAuthUrl = function (opt_opts) {
var opts = opt_opts || {};
opts.response_type = opts.response_type || 'code';
opts.client_id = opts.client_id || this._clientId;
opts.redirect_uri = opts.redirect_uri || this._redirectUri;
// Allow scopes to be passed either as array or a string
if (opts.scope instanceof Array) {
opts.scope = opts.scope.join(' ');
}
var rootUrl = this._opts.authBaseUrl || OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_;
return rootUrl + '?' + querystring.stringify(opts);
};
/**
* Gets the access token for the given code.
* @param {string} code The authorization code.
* @param {function=} callback Optional callback fn.
*/
OAuth2Client.prototype.getToken = function (code, callback) {
var uri = this._opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_;
var values = {
code: code,
client_id: this._clientId,
client_secret: this._clientSecret,
redirect_uri: this._redirectUri,
grant_type: 'authorization_code'
};
this.transporter.request({ method: 'POST', uri: uri, form: values, json: true }, function (err, tokens, response) {
if (!err && tokens && tokens.expires_in) {
tokens.expiry_date =
((new Date()).getTime() + (tokens.expires_in * 1000));
delete tokens.expires_in;
}
var done = callback || noop;
done(err, tokens, response);
});
};
/**
* Refreshes the access token.
* @param {string} refresh_token Existing refresh token.
* @param {function=} callback Optional callback.
* @private
*/
OAuth2Client.prototype.refreshToken = function (refresh_token, callback) {
var uri = this._opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_;
var values = {
refresh_token: refresh_token,
client_id: this._clientId,
client_secret: this._clientSecret,
grant_type: 'refresh_token'
};
// request for new token
return this.transporter.request({ method: 'POST', uri: uri, form: values, json: true }, function (err, tokens, response) {
if (!err && tokens && tokens.expires_in) {
tokens.expiry_date =
((new Date()).getTime() + (tokens.expires_in * 1000));
delete tokens.expires_in;
}
var done = callback || noop;
done(err, tokens, response);
});
};
/**
* Retrieves the access token using refresh token
*
* @deprecated use getRequestMetadata instead.
* @param {function} callback callback
*/
OAuth2Client.prototype.refreshAccessToken = function (callback) {
var _this = this;
if (!this.credentials.refresh_token) {
callback(new Error('No refresh token is set.'), null);
return;
}
this.refreshToken(this.credentials.refresh_token, function (err, result, response) {
if (err) {
callback(err, null, response);
}
else {
var tokens = result;
tokens.refresh_token = _this.credentials.refresh_token;
_this.credentials = tokens;
callback(null, _this.credentials, response);
}
});
};
/**
* Get a non-expired access token, after refreshing if necessary
*
* @param {function} callback Callback to call with the access token
*/
OAuth2Client.prototype.getAccessToken = function (callback) {
var expiryDate = this.credentials.expiry_date;
// if no expiry time, assume it's not expired
var isTokenExpired = expiryDate ? expiryDate <= (new Date()).getTime() : false;
if (!this.credentials.access_token && !this.credentials.refresh_token) {
return callback(new Error('No access or refresh token is set.'), null);
}
var shouldRefresh = !this.credentials.access_token || isTokenExpired;
if (shouldRefresh && this.credentials.refresh_token) {
if (!this.credentials.refresh_token) {
return callback(new Error('No refresh token is set.'), null);
}
this.refreshAccessToken(function (err, tokens, response) {
if (err) {
return callback(err, null, response);
}
if (!tokens || (tokens && !tokens.access_token)) {
return callback(new Error('Could not refresh access token.'), null, response);
}
return callback(null, tokens.access_token, response);
});
}
else {
return callback(null, this.credentials.access_token, null);
}
};
/**
* getRequestMetadata obtains auth metadata to be used by requests.
*
* getRequestMetadata is the main authentication interface. It takes an
* optional uri which when present is the endpoint being accessed, and a
* callback func(err, metadata_obj, response) where metadata_obj contains
* authorization metadata fields and response is an optional response object.
*
* In OAuth2Client, metadata_obj has the form.
*
* {Authorization: 'Bearer <access_token_value>'}
*
* @param {string} opt_uri the Uri being authorized
* @param {function} metadataCb the func described above
*/
OAuth2Client.prototype.getRequestMetadata = function (opt_uri, metadataCb) {
var _this = this;
var thisCreds = this.credentials;
if (!thisCreds.access_token && !thisCreds.refresh_token && !this.apiKey) {
return metadataCb(new Error('No access, refresh token or API key is set.'), null);
}
// if no expiry time, assume it's not expired
var expiryDate = thisCreds.expiry_date;
var isTokenExpired = expiryDate ? expiryDate <= (new Date()).getTime() : false;
if (thisCreds.access_token && !isTokenExpired) {
thisCreds.token_type = thisCreds.token_type || 'Bearer';
var headers = {
Authorization: thisCreds.token_type + ' ' + thisCreds.access_token
};
return metadataCb(null, headers, null);
}
if (this.apiKey) {
return metadataCb(null, {}, null);
}
return this.refreshToken(thisCreds.refresh_token, function (err, tokens, response) {
// If the error code is 403 or 404, go to the else so the error
// message is replaced. Otherwise, return the error.
if (err && err.code != 403 &&
err.code != 404) {
return metadataCb(err, null, response);
}
else {
if (!tokens || (tokens && !tokens.access_token)) {
return metadataCb(new Error('Could not refresh access token.'), null, response);
}
var credentials = _this.credentials;
credentials.token_type = credentials.token_type || 'Bearer';
tokens.refresh_token = credentials.refresh_token;
_this.credentials = tokens;
var headers = {
Authorization: credentials.token_type + ' ' + tokens.access_token
};
return metadataCb(err, headers, response);
}
});
};
/**
* Revokes the access given to token.
* @param {string} token The existing token to be revoked.
* @param {function=} callback Optional callback fn.
*/
OAuth2Client.prototype.revokeToken = function (token, callback) {
this.transporter.request({
uri: OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_ + '?' +
querystring.stringify({ token: token }),
json: true
}, callback);
};
/**
* Revokes access token and clears the credentials object
* @param {Function=} callback callback
*/
OAuth2Client.prototype.revokeCredentials = function (callback) {
var token = this.credentials.access_token;
this.credentials = {};
if (token) {
this.revokeToken(token, callback);
}
else {
callback(new transporters_1.RequestError('No access token to revoke.'), null, null);
}
};
/**
* Provides a request implementation with OAuth 2.0 flow.
* If credentials have a refresh_token, in cases of HTTP
* 401 and 403 responses, it automatically asks for a new
* access token and replays the unsuccessful request.
* @param {object} opts Request options.
* @param {function} callback callback.
* @return {Request} Request object
*/
OAuth2Client.prototype.request = function (opts, callback) {
/* jshint latedef:false */
var _this = this;
// Callbacks will close over this to ensure that we only retry once
var retry = true;
var unusedUri = null;
// Declare authCb upfront to avoid the linter complaining about use before
// declaration.
var authCb;
// Hook the callback routine to call the _postRequest method.
var postRequestCb = function (err, body, resp) {
var statusCode = resp && resp.statusCode;
// Automatically retry 401 and 403 responses
// if err is set and is unrelated to response
// then getting credentials failed, and retrying won't help
if (retry && (statusCode === 401 || statusCode === 403) &&
(!err || err.code === statusCode)) {
/* 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;
// Force token refresh
_this.refreshAccessToken(function () {
_this.getRequestMetadata(unusedUri, authCb);
});
}
else {
_this.postRequest(err, body, resp, callback);
}
};
authCb = function (err, headers, response) {
if (err) {
postRequestCb(err, null, response);
}
else {
if (headers) {
opts.headers = opts.headers || {};
opts.headers.Authorization = headers.Authorization;
}
if (_this.apiKey) {
if (opts.qs) {
opts.qs = merge({}, opts.qs, { key: _this.apiKey });
}
else {
opts.qs = { key: _this.apiKey };
}
}
return _this._makeRequest(opts, postRequestCb);
}
};
return this.getRequestMetadata(unusedUri, authCb);
};
/**
* Makes a request without paying attention to refreshing or anything
* Assumes that all credentials are set correctly.
* @param {object} opts Options for request
* @param {Function} callback callback function
* @return {Request} The request object created
*/
OAuth2Client.prototype._makeRequest = function (opts, callback) {
return this.transporter.request(opts, callback);
};
/**
* Allows inheriting classes to inspect and alter the request result.
* @param {object} err Error result.
* @param {object} result The result.
* @param {object} result The HTTP response.
* @param {Function} callback The callback.
* @private
*/
OAuth2Client.prototype.postRequest = function (err, result, response, callback) {
callback(err, result, response);
};
/**
* Verify id token is token by checking the certs and audience
* @param {string} idToken ID Token.
* @param {(string|Array.<string>)} audience The audience to verify against the ID Token
* @param {function=} callback Callback supplying GoogleLogin if successful
*/
OAuth2Client.prototype.verifyIdToken = function (idToken, audience, callback) {
var _this = this;
if (!idToken || !callback) {
throw new Error('The verifyIdToken method requires both ' +
'an ID Token and a callback method');
}
this.getFederatedSignonCerts((function (err, certs) {
if (err) {
callback(err, null);
}
var login;
try {
login = _this.verifySignedJwtWithCerts(idToken, certs, audience, OAuth2Client.ISSUERS_);
}
catch (err) {
callback(err);
return;
}
callback(null, login);
}).bind(this));
};
/**
* Gets federated sign-on certificates to use for verifying identity tokens.
* Returns certs as array structure, where keys are key ids, and values
* are PEM encoded certificates.
* @param {function=} callback Callback supplying the certificates
*/
OAuth2Client.prototype.getFederatedSignonCerts = function (callback) {
var _this = this;
var nowTime = (new Date()).getTime();
if (this._certificateExpiry &&
(nowTime < this._certificateExpiry.getTime())) {
callback(null, this._certificateCache);
return;
}
this.transporter.request({
method: 'GET',
uri: OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_CERTS_URL_,
json: true
}, function (err, body, response) {
if (err) {
callback(new transporters_1.RequestError('Failed to retrieve verification certificates: ' + err), null, response);
return;
}
var cacheControl = response.headers['cache-control'];
var cacheAge = -1;
if (cacheControl) {
var pattern = new RegExp('max-age=([0-9]*)');
var regexResult = pattern.exec(cacheControl);
if (regexResult.length === 2) {
// Cache results with max-age (in seconds)
cacheAge = Number(regexResult[1]) * 1000; // milliseconds
}
}
var now = new Date();
_this._certificateExpiry =
cacheAge === -1 ? null : new Date(now.getTime() + cacheAge);
_this._certificateCache = body;
callback(null, body, response);
});
};
/**
* Verify the id token is signed with the correct certificate
* and is from the correct audience.
* @param {string} jwt The jwt to verify (The ID Token in this case).
* @param {array} certs The array of certs to test the jwt against.
* @param {(string|Array.<string>)} requiredAudience The audience to test the jwt against.
* @param {array} issuers The allowed issuers of the jwt (Optional).
* @param {string} maxExpiry The max expiry the certificate can be (Optional).
* @return {LoginTicket} Returns a LoginTicket on verification.
*/
OAuth2Client.prototype.verifySignedJwtWithCerts = function (jwt, certs, requiredAudience, issuers, maxExpiry) {
if (!maxExpiry) {
maxExpiry = OAuth2Client.MAX_TOKEN_LIFETIME_SECS_;
}
var segments = jwt.split('.');
if (segments.length !== 3) {
throw new Error('Wrong number of segments in token: ' + jwt);
}
var signed = segments[0] + '.' + segments[1];
var signature = segments[2];
var envelope;
var payload;
try {
envelope = JSON.parse(this.decodeBase64(segments[0]));
}
catch (err) {
throw new Error('Can\'t parse token envelope: ' + segments[0]);
}
if (!envelope) {
throw new Error('Can\'t parse token envelope: ' + segments[0]);
}
try {
payload = JSON.parse(this.decodeBase64(segments[1]));
}
catch (err) {
throw new Error('Can\'t parse token payload: ' + segments[0]);
}
if (!payload) {
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_1.PemVerifier();
var verified = pemVerifier.verify(pem, signed, signature, 'base64');
if (!verified) {
throw new Error('Invalid token signature: ' + jwt);
}
if (!payload.iat) {
throw new Error('No issue time in token: ' + JSON.stringify(payload));
}
if (!payload.exp) {
throw new Error('No expiration time in token: ' + JSON.stringify(payload));
}
var iat = parseInt(payload.iat, 10);
var exp = parseInt(payload.exp, 10);
var now = new Date().getTime() / 1000;
if (exp >= now + maxExpiry) {
throw new Error('Expiration time too far in future: ' + JSON.stringify(payload));
}
var earliest = iat - OAuth2Client.CLOCK_SKEW_SECS_;
var latest = exp + OAuth2Client.CLOCK_SKEW_SECS_;
if (now < earliest) {
throw new Error('Token used too early, ' + now + ' < ' + earliest + ': ' +
JSON.stringify(payload));
}
if (now > latest) {
throw new Error('Token used too late, ' + now + ' > ' + latest + ': ' +
JSON.stringify(payload));
}
if (issuers && issuers.indexOf(payload.iss) < 0) {
throw new Error('Invalid issuer, expected one of [' + issuers + '], but got ' +
payload.iss);
}
// Check the audience matches if we have one
if (typeof requiredAudience !== 'undefined' && requiredAudience !== null) {
var aud = payload.aud;
var audVerified = false;
// If the requiredAudience is an array, check if it contains token
// audience
if (requiredAudience.constructor === Array) {
audVerified = (requiredAudience.indexOf(aud) > -1);
}
else {
audVerified = (aud === requiredAudience);
}
if (!audVerified) {
throw new Error('Wrong recipient, payload audience != requiredAudience');
}
}
return new loginticket_1.LoginTicket(envelope, payload);
};
/**
* This is a utils method to decode a base64 string
* @param {string} b64String The string to base64 decode
* @return {string} The decoded string
*/
OAuth2Client.prototype.decodeBase64 = function (b64String) {
var buffer = new Buffer(b64String, 'base64');
return buffer.toString('utf8');
};
return OAuth2Client;
}(authclient_1.AuthClient));
/**
* The base URL for auth endpoints.
*/
OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_ = 'https://accounts.google.com/o/oauth2/auth';
/**
* The base endpoint for token retrieval.
*/
OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_ = 'https://accounts.google.com/o/oauth2/token';
/**
* The base endpoint to revoke tokens.
*/
OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_ = 'https://accounts.google.com/o/oauth2/revoke';
/**
* Google Sign on certificates.
*/
OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_CERTS_URL_ = 'https://www.googleapis.com/oauth2/v1/certs';
/**
* Clock skew - five minutes in seconds
*/
OAuth2Client.CLOCK_SKEW_SECS_ = 300;
/**
* Max Token Lifetime is one day in seconds
*/
OAuth2Client.MAX_TOKEN_LIFETIME_SECS_ = 86400;
/**
* The allowed oauth token issuers.
*/
OAuth2Client.ISSUERS_ = ['accounts.google.com', 'https://accounts.google.com'];
exports.OAuth2Client = OAuth2Client;
//# sourceMappingURL=oauth2client.js.map

View File

@@ -0,0 +1,125 @@
/**
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var oauth2client_1 = require("./oauth2client");
var UserRefreshClient = (function (_super) {
__extends(UserRefreshClient, _super);
/**
* User Refresh Token credentials.
*
* @param {string} clientId The authentication client ID.
* @param {string} clientSecret The authentication client secret.
* @param {string} refreshToken The authentication refresh token.
* @constructor
*/
function UserRefreshClient(clientId, clientSecret, refreshToken) {
var _this = _super.call(this, clientId, clientSecret) || this;
// Named to avoid collision with the method refreshToken_
_this._refreshToken = refreshToken;
return _this;
}
// Executes the given callback if it is not null.
UserRefreshClient.prototype.callback = function (c, err, res) {
if (c) {
c(err, res);
}
};
/**
* Refreshes the access token.
* @param {object=} ignored_
* @param {function=} callback Optional callback.
* @private
*/
UserRefreshClient.prototype.refreshToken = function (ignored_, callback) {
return _super.prototype.refreshToken.call(this, this._refreshToken, callback);
};
/**
* Create a UserRefreshClient credentials instance using the given input
* options.
* @param {object=} json The input object.
* @param {function=} callback Optional callback.
*/
UserRefreshClient.prototype.fromJSON = function (json, callback) {
if (!json) {
this.callback(callback, new Error('Must pass in a JSON object containing the user refresh token'));
return;
}
if (json.type !== 'authorized_user') {
this.callback(callback, new Error('The incoming JSON object does not have the "authorized_user" type'));
return;
}
if (!json.client_id) {
this.callback(callback, new Error('The incoming JSON object does not contain a client_id field'));
return;
}
if (!json.client_secret) {
this.callback(callback, new Error('The incoming JSON object does not contain a client_secret field'));
return;
}
if (!json.refresh_token) {
this.callback(callback, new Error('The incoming JSON object does not contain a refresh_token field'));
return;
}
this._clientId = json.client_id;
this._clientSecret = json.client_secret;
this._refreshToken = json.refresh_token;
this.credentials.refresh_token = json.refresh_token;
this.callback(callback);
};
/**
* Create a UserRefreshClient credentials instance using the given input
* stream.
* @param {object=} stream The input stream.
* @param {function=} callback Optional callback.
*/
UserRefreshClient.prototype.fromStream = function (stream, callback) {
var _this = this;
if (!stream) {
setImmediate(function () {
_this.callback(callback, new Error('Must pass in a stream containing the user refresh token.'));
});
return;
}
var s = '';
stream.setEncoding('utf8');
stream.on('data', function (chunk) {
s += chunk;
});
stream.on('end', function () {
try {
var data = JSON.parse(s);
_this.fromJSON(data, callback);
}
catch (err) {
_this.callback(callback, err);
}
});
};
return UserRefreshClient;
}(oauth2client_1.OAuth2Client));
exports.UserRefreshClient = UserRefreshClient;
//# sourceMappingURL=refreshclient.js.map