google-auth-library
Advanced tools
Comparing version 1.0.0-alpha.1 to 1.0.0
@@ -100,3 +100,3 @@ "use strict"; | ||
case 0: | ||
url = this.opts.tokenUrl || Compute._GOOGLE_OAUTH2_TOKEN_URL; | ||
url = this.tokenUrl || Compute._GOOGLE_OAUTH2_TOKEN_URL; | ||
res = null; | ||
@@ -103,0 +103,0 @@ _a.label = 1; |
@@ -21,2 +21,3 @@ /** | ||
token_type?: string | null; | ||
id_token?: string | null; | ||
} | ||
@@ -23,0 +24,0 @@ export interface CredentialRequest { |
@@ -35,4 +35,4 @@ /// <reference types="node" /> | ||
readonly isGCE: boolean | undefined; | ||
private _getDefaultProjectIdPromise; | ||
private _cachedProjectId; | ||
cachedProjectId: string; | ||
jsonContent: JWTInput | null; | ||
@@ -73,3 +73,3 @@ cachedCredential: OAuth2Client | null; | ||
*/ | ||
_checkIsGCE(): Promise<boolean>; | ||
_checkIsGCE(isRetry?: boolean): Promise<boolean>; | ||
/** | ||
@@ -76,0 +76,0 @@ * Attempts to load default credentials from the environment variable path.. |
@@ -83,11 +83,2 @@ "use strict"; | ||
}); | ||
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 | ||
}); | ||
GoogleAuth.prototype.getDefaultProjectId = function (callback) { | ||
@@ -104,49 +95,59 @@ if (callback) { | ||
GoogleAuth.prototype.getDefaultProjectIdAsync = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var projectId, _a, _b, _c; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
// 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) | ||
if (this._cachedProjectId) { | ||
return [2 /*return*/, this._cachedProjectId]; | ||
// 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) { | ||
return Promise.resolve(this._cachedProjectId); | ||
} | ||
if (!this._getDefaultProjectIdPromise) { | ||
this._getDefaultProjectIdPromise = | ||
new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { | ||
var projectId, _a, _b, _c, e_1; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
_d.trys.push([0, 7, , 8]); | ||
_c = this.getProductionProjectId(); | ||
if (_c) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this.getFileProjectId()]; | ||
case 1: | ||
_c = (_d.sent()); | ||
_d.label = 2; | ||
case 2: | ||
_b = _c; | ||
if (_b) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, this.getDefaultServiceProjectId()]; | ||
case 3: | ||
_b = (_d.sent()); | ||
_d.label = 4; | ||
case 4: | ||
_a = _b; | ||
if (_a) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, this.getGCEProjectId()]; | ||
case 5: | ||
_a = (_d.sent()); | ||
_d.label = 6; | ||
case 6: | ||
projectId = _a; | ||
this._cachedProjectId = projectId; | ||
resolve(projectId); | ||
return [3 /*break*/, 8]; | ||
case 7: | ||
e_1 = _d.sent(); | ||
reject(e_1); | ||
return [3 /*break*/, 8]; | ||
case 8: return [2 /*return*/]; | ||
} | ||
_c = this.getProductionProjectId(); | ||
if (_c) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this.getFileProjectId()]; | ||
case 1: | ||
_c = (_d.sent()); | ||
_d.label = 2; | ||
case 2: | ||
_b = _c; | ||
if (_b) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, this.getDefaultServiceProjectId()]; | ||
case 3: | ||
_b = (_d.sent()); | ||
_d.label = 4; | ||
case 4: | ||
_a = _b; | ||
if (_a) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, this.getGCEProjectId()]; | ||
case 5: | ||
_a = (_d.sent()); | ||
_d.label = 6; | ||
case 6: | ||
projectId = _a; | ||
if (projectId) { | ||
this._cachedProjectId = projectId; | ||
} | ||
return [2 /*return*/, projectId]; | ||
} | ||
}); | ||
}); | ||
}); | ||
}); }); | ||
} | ||
return this._getDefaultProjectIdPromise; | ||
}; | ||
@@ -181,15 +182,15 @@ /** | ||
return __awaiter(this, void 0, void 0, function () { | ||
var credential, projectId, gce, e_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var _a, credential, projectId, gce, e_2; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
// If we've already got a cached credential, just return it. | ||
if (this.cachedCredential) { | ||
return [2 /*return*/, { | ||
credential: this.cachedCredential, | ||
projectId: this._cachedProjectId | ||
}]; | ||
} | ||
return [4 /*yield*/, this._tryGetApplicationCredentialsFromEnvironmentVariable()]; | ||
case 1: | ||
if (!this.cachedCredential) return [3 /*break*/, 2]; | ||
_a = { | ||
credential: this.cachedCredential | ||
}; | ||
return [4 /*yield*/, this.getDefaultProjectIdAsync()]; | ||
case 1: return [2 /*return*/, (_a.projectId = _b.sent(), | ||
_a)]; | ||
case 2: return [4 /*yield*/, this._tryGetApplicationCredentialsFromEnvironmentVariable()]; | ||
case 3: | ||
// Check for the existence of a local environment variable pointing to the | ||
@@ -199,24 +200,24 @@ // location of the credential file. This is typically used in local | ||
credential = | ||
_a.sent(); | ||
if (!credential) return [3 /*break*/, 3]; | ||
_b.sent(); | ||
if (!credential) return [3 /*break*/, 5]; | ||
this.cachedCredential = credential; | ||
return [4 /*yield*/, this.getDefaultProjectId()]; | ||
case 2: | ||
projectId = _a.sent(); | ||
case 4: | ||
projectId = _b.sent(); | ||
return [2 /*return*/, { credential: credential, projectId: projectId }]; | ||
case 3: return [4 /*yield*/, this._tryGetApplicationCredentialsFromWellKnownFile()]; | ||
case 4: | ||
case 5: return [4 /*yield*/, this._tryGetApplicationCredentialsFromWellKnownFile()]; | ||
case 6: | ||
// Look in the well-known credential file location. | ||
credential = _a.sent(); | ||
if (!credential) return [3 /*break*/, 6]; | ||
credential = _b.sent(); | ||
if (!credential) return [3 /*break*/, 8]; | ||
this.cachedCredential = credential; | ||
return [4 /*yield*/, this.getDefaultProjectId()]; | ||
case 5: | ||
projectId = _a.sent(); | ||
case 7: | ||
projectId = _b.sent(); | ||
return [2 /*return*/, { credential: credential, projectId: projectId }]; | ||
case 6: | ||
_a.trys.push([6, 8, , 9]); | ||
case 8: | ||
_b.trys.push([8, 10, , 11]); | ||
return [4 /*yield*/, this._checkIsGCE()]; | ||
case 7: | ||
gce = _a.sent(); | ||
case 9: | ||
gce = _b.sent(); | ||
if (gce) { | ||
@@ -232,8 +233,8 @@ // For GCE, just return a default ComputeClient. It will take care of | ||
} | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
e_1 = _a.sent(); | ||
return [3 /*break*/, 11]; | ||
case 10: | ||
e_2 = _b.sent(); | ||
throw new Error('Unexpected error while acquiring application default credentials: ' + | ||
e_1.message); | ||
case 9: return [2 /*return*/]; | ||
e_2.message); | ||
case 11: return [2 /*return*/]; | ||
} | ||
@@ -248,5 +249,6 @@ }); | ||
*/ | ||
GoogleAuth.prototype._checkIsGCE = function () { | ||
GoogleAuth.prototype._checkIsGCE = function (isRetry) { | ||
if (isRetry === void 0) { isRetry = false; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var res, e_2; | ||
var res, e_3, isDNSError, ae, is5xx; | ||
return __generator(this, function (_a) { | ||
@@ -263,3 +265,3 @@ switch (_a.label) { | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
_a.trys.push([1, 3, , 8]); | ||
return [4 /*yield*/, this.transporter.request({ url: 'http://metadata.google.internal' })]; | ||
@@ -270,13 +272,23 @@ case 2: | ||
res && res.headers && res.headers['metadata-flavor'] === 'Google'; | ||
return [3 /*break*/, 4]; | ||
return [3 /*break*/, 8]; | ||
case 3: | ||
e_2 = _a.sent(); | ||
if (e_2.code !== 'ENOTFOUND') { | ||
// Unexpected error occurred. TODO(ofrobots): retry if this was a | ||
// transient error. | ||
throw e_2; | ||
e_3 = _a.sent(); | ||
isDNSError = e_3.code === 'ENOTFOUND'; | ||
ae = e_3; | ||
is5xx = ae.response && | ||
(ae.response.status >= 500 && ae.response.status < 600); | ||
if (!is5xx) return [3 /*break*/, 6]; | ||
if (!!isRetry) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, this._checkIsGCE(true)]; | ||
case 4: return [2 /*return*/, _a.sent()]; | ||
case 5: throw e_3; | ||
case 6: | ||
if (!isDNSError) { | ||
throw e_3; | ||
} | ||
_a.label = 7; | ||
case 7: | ||
this.checkIsGCE = false; | ||
return [3 /*break*/, 4]; | ||
case 4: return [2 /*return*/, this.checkIsGCE]; | ||
return [3 /*break*/, 8]; | ||
case 8: return [2 /*return*/, this.checkIsGCE]; | ||
} | ||
@@ -528,3 +540,3 @@ }); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var r, e_3; | ||
var r, e_4; | ||
return __generator(this, function (_a) { | ||
@@ -542,3 +554,3 @@ switch (_a.label) { | ||
case 2: | ||
e_3 = _a.sent(); | ||
e_4 = _a.sent(); | ||
return [3 /*break*/, 3]; | ||
@@ -600,3 +612,3 @@ case 3: return [2 /*return*/, null]; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var r, e_4; | ||
var r, e_5; | ||
return __generator(this, function (_a) { | ||
@@ -619,3 +631,3 @@ switch (_a.label) { | ||
case 3: | ||
e_4 = _a.sent(); | ||
e_5 = _a.sent(); | ||
// Ignore any errors | ||
@@ -622,0 +634,0 @@ return [2 /*return*/, null]; |
@@ -21,8 +21,15 @@ /// <reference types="node" /> | ||
import { GetTokenResponse, OAuth2Client, RequestMetadataResponse } from './oauth2client'; | ||
export interface JWTOptions { | ||
email?: string; | ||
keyFile?: string; | ||
key?: string; | ||
scopes?: string | string[]; | ||
subject?: string; | ||
} | ||
export declare class JWT extends OAuth2Client { | ||
email?: string; | ||
keyFile?: string | null; | ||
key?: string | null; | ||
scopes?: string | string[] | null; | ||
scope?: string | null; | ||
keyFile?: string; | ||
key?: string; | ||
scopes?: string | string[]; | ||
scope?: string; | ||
subject?: string; | ||
@@ -42,3 +49,4 @@ gtoken: GoogleToken; | ||
*/ | ||
constructor(email?: string, keyFile?: string | null, key?: string | null, scopes?: string | string[] | null, subject?: string); | ||
constructor(options: JWTOptions); | ||
constructor(email?: string, keyFile?: string, key?: string, scopes?: string | string[], subject?: string); | ||
/** | ||
@@ -45,0 +53,0 @@ * Creates a copy of the credential with the specified scopes. |
@@ -69,21 +69,12 @@ "use strict"; | ||
__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) { | ||
function JWT(optionsOrEmail, 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; | ||
var opts = (optionsOrEmail && typeof optionsOrEmail === 'object') ? | ||
optionsOrEmail : | ||
{ email: optionsOrEmail, keyFile: keyFile, key: key, scopes: scopes, subject: subject }; | ||
_this.email = opts.email; | ||
_this.keyFile = opts.keyFile; | ||
_this.key = opts.key; | ||
_this.scopes = opts.scopes; | ||
_this.subject = opts.subject; | ||
_this.credentials = { refresh_token: 'jwt-placeholder', expiry_date: 1 }; | ||
@@ -98,3 +89,9 @@ return _this; | ||
JWT.prototype.createScoped = function (scopes) { | ||
return new JWT(this.email, this.keyFile, this.key, scopes, this.subject); | ||
return new JWT({ | ||
email: this.email, | ||
keyFile: this.keyFile, | ||
key: this.key, | ||
scopes: scopes, | ||
subject: this.subject | ||
}); | ||
}; | ||
@@ -101,0 +98,0 @@ /** |
@@ -17,3 +17,2 @@ /** | ||
export declare class LoginTicket { | ||
private static readonly USER_ATTR; | ||
private envelope?; | ||
@@ -25,8 +24,8 @@ private payload?; | ||
* @param {string} env Envelope of the jwt | ||
* @param {string} pay Payload of the jwt | ||
* @param {TokenPayload} pay Payload of the jwt | ||
* @constructor | ||
*/ | ||
constructor(env?: string, pay?: string); | ||
constructor(env?: string, pay?: TokenPayload); | ||
getEnvelope(): string | undefined; | ||
getPayload(): string | undefined; | ||
getPayload(): TokenPayload | undefined; | ||
/** | ||
@@ -37,3 +36,3 @@ * Create a simple class to extract user ID from an ID Token | ||
*/ | ||
getUserId(): (() => string) | null; | ||
getUserId(): string | null; | ||
/** | ||
@@ -47,4 +46,93 @@ * Returns attributes from the login ticket. This can contain | ||
envelope: string | undefined; | ||
payload: string | undefined; | ||
payload: TokenPayload | undefined; | ||
}; | ||
} | ||
export interface TokenPayload { | ||
/** | ||
* The Issuer Identifier for the Issuer of the response. Always | ||
* https://accounts.google.com or accounts.google.com for Google ID tokens. | ||
*/ | ||
iss: string; | ||
/** | ||
* Access token hash. Provides validation that the access token is tied to the | ||
* identity token. If the ID token is issued with an access token in the | ||
* server flow, this is always included. This can be used as an alternate | ||
* mechanism to protect against cross-site request forgery attacks, but if you | ||
* follow Step 1 and Step 3 it is not necessary to verify the access token. | ||
*/ | ||
at_hash?: string; | ||
/** | ||
* True if the user's e-mail address has been verified; otherwise false. | ||
*/ | ||
email_verified?: boolean; | ||
/** | ||
* An identifier for the user, unique among all Google accounts and never | ||
* reused. A Google account can have multiple emails at different points in | ||
* time, but the sub value is never changed. Use sub within your application | ||
* as the unique-identifier key for the user. | ||
*/ | ||
sub: string; | ||
/** | ||
* The client_id of the authorized presenter. This claim is only needed when | ||
* the party requesting the ID token is not the same as the audience of the ID | ||
* token. This may be the case at Google for hybrid apps where a web | ||
* application and Android app have a different client_id but share the same | ||
* project. | ||
*/ | ||
azp?: string; | ||
/** | ||
* The user's email address. This may not be unique and is not suitable for | ||
* use as a primary key. Provided only if your scope included the string | ||
* "email". | ||
*/ | ||
email?: string; | ||
/** | ||
* The URL of the user's profile page. Might be provided when: | ||
* - The request scope included the string "profile" | ||
* - The ID token is returned from a token refresh | ||
* - When profile claims are present, you can use them to update your app's | ||
* user records. Note that this claim is never guaranteed to be present. | ||
*/ | ||
profile?: string; | ||
/** | ||
* The URL of the user's profile picture. Might be provided when: | ||
* - The request scope included the string "profile" | ||
* - The ID token is returned from a token refresh | ||
* - When picture claims are present, you can use them to update your app's | ||
* user records. Note that this claim is never guaranteed to be present. | ||
*/ | ||
picture?: string; | ||
/** | ||
* The user's full name, in a displayable form. Might be provided when: | ||
* - The request scope included the string "profile" | ||
* - The ID token is returned from a token refresh | ||
* - When name claims are present, you can use them to update your app's user | ||
* records. Note that this claim is never guaranteed to be present. | ||
*/ | ||
name?: string; | ||
/** | ||
* Identifies the audience that this ID token is intended for. It must be one | ||
* of the OAuth 2.0 client IDs of your application. | ||
*/ | ||
aud: string; | ||
/** | ||
* The time the ID token was issued, represented in Unix time (integer | ||
* seconds). | ||
*/ | ||
iat: number; | ||
/** | ||
* The time the ID token expires, represented in Unix time (integer seconds). | ||
*/ | ||
exp: number; | ||
/** | ||
* The value of the nonce supplied by your app in the authentication request. | ||
* You should enforce protection against replay attacks by ensuring it is | ||
* presented only once. | ||
*/ | ||
nonce?: string; | ||
/** | ||
* The hosted G Suite domain of the user. Provided only if the user belongs to | ||
* a hosted domain. | ||
*/ | ||
hd?: string; | ||
} |
@@ -23,3 +23,3 @@ "use strict"; | ||
* @param {string} env Envelope of the jwt | ||
* @param {string} pay Payload of the jwt | ||
* @param {TokenPayload} pay Payload of the jwt | ||
* @constructor | ||
@@ -44,4 +44,4 @@ */ | ||
var payload = this.getPayload(); | ||
if (payload && payload[LoginTicket.USER_ATTR]) { | ||
return payload[LoginTicket.USER_ATTR]; | ||
if (payload && payload.sub) { | ||
return payload.sub; | ||
} | ||
@@ -59,3 +59,2 @@ return null; | ||
}; | ||
LoginTicket.USER_ATTR = 'sub'; | ||
return LoginTicket; | ||
@@ -62,0 +61,0 @@ }()); |
@@ -23,7 +23,116 @@ /// <reference types="node" /> | ||
import { LoginTicket } from './loginticket'; | ||
export declare enum CodeChallengeMethod { | ||
Plain = "plain", | ||
S256 = "S256", | ||
} | ||
export interface GetTokenOptions { | ||
code: string; | ||
codeVerifier?: string; | ||
} | ||
export interface GenerateAuthUrlOpts { | ||
/** | ||
* Recommended. Indicates whether your application can refresh access tokens | ||
* when the user is not present at the browser. Valid parameter values are | ||
* 'online', which is the default value, and 'offline'. Set the value to | ||
* 'offline' if your application needs to refresh access tokens when the user | ||
* is not present at the browser. This value instructs the Google | ||
* authorization server to return a refresh token and an access token the | ||
* first time that your application exchanges an authorization code for | ||
* tokens. | ||
*/ | ||
access_type?: string; | ||
/** | ||
* The 'response_type' will always be set to 'CODE'. | ||
*/ | ||
response_type?: string; | ||
/** | ||
* The client ID for your application. The value passed into the constructor | ||
* will be used if not provided. You can find this value in the API Console. | ||
*/ | ||
client_id?: string; | ||
/** | ||
* Determines where the API server redirects the user after the user | ||
* completes the authorization flow. The value must exactly match one of the | ||
* 'redirect_uri' values listed for your project in the API Console. Note that | ||
* the http or https scheme, case, and trailing slash ('/') must all match. | ||
* The value passed into the constructor will be used if not provided. | ||
*/ | ||
redirect_uri?: string; | ||
/** | ||
* Required. A space-delimited list of scopes that identify the resources that | ||
* your application could access on the user's behalf. These values inform the | ||
* consent screen that Google displays to the user. Scopes enable your | ||
* application to only request access to the resources that it needs while | ||
* also enabling users to control the amount of access that they grant to your | ||
* application. Thus, there is an inverse relationship between the number of | ||
* scopes requested and the likelihood of obtaining user consent. The | ||
* OAuth 2.0 API Scopes document provides a full list of scopes that you might | ||
* use to access Google APIs. We recommend that your application request | ||
* access to authorization scopes in context whenever possible. By requesting | ||
* access to user data in context, via incremental authorization, you help | ||
* users to more easily understand why your application needs the access it is | ||
* requesting. | ||
*/ | ||
scope?: string[] | string; | ||
/** | ||
* Recommended. Specifies any string value that your application uses to | ||
* maintain state between your authorization request and the authorization | ||
* server's response. The server returns the exact value that you send as a | ||
* name=value pair in the hash (#) fragment of the 'redirect_uri' after the | ||
* user consents to or denies your application's access request. You can use | ||
* this parameter for several purposes, such as directing the user to the | ||
* correct resource in your application, sending nonces, and mitigating | ||
* cross-site request forgery. Since your redirect_uri can be guessed, using a | ||
* state value can increase your assurance that an incoming connection is the | ||
* result of an authentication request. If you generate a random string or | ||
* encode the hash of a cookie or another value that captures the client's | ||
* state, you can validate the response to additionally ensure that the | ||
* request and response originated in the same browser, providing protection | ||
* against attacks such as cross-site request forgery. See the OpenID Connect | ||
* documentation for an example of how to create and confirm a state token. | ||
*/ | ||
state?: string; | ||
/** | ||
* Optional. Enables applications to use incremental authorization to request | ||
* access to additional scopes in context. If you set this parameter's value | ||
* to true and the authorization request is granted, then the new access token | ||
* will also cover any scopes to which the user previously granted the | ||
* application access. See the incremental authorization section for examples. | ||
*/ | ||
include_granted_scopes?: boolean; | ||
/** | ||
* Optional. If your application knows which user is trying to authenticate, | ||
* it can use this parameter to provide a hint to the Google Authentication | ||
* Server. The server uses the hint to simplify the login flow either by | ||
* prefilling the email field in the sign-in form or by selecting the | ||
* appropriate multi-login session. Set the parameter value to an email | ||
* address or sub identifier, which is equivalent to the user's Google ID. | ||
*/ | ||
login_hint?: string; | ||
/** | ||
* Optional. A space-delimited, case-sensitive list of prompts to present the | ||
* user. If you don't specify this parameter, the user will be prompted only | ||
* the first time your app requests access. Possible values are: | ||
* | ||
* 'none' - Donot display any authentication or consent screens. Must not be | ||
* specified with other values. | ||
* 'consent' - Prompt the user for consent. | ||
* 'select_account' - Prompt the user to select an account. | ||
*/ | ||
prompt?: string; | ||
/** | ||
* Recommended. Specifies what method was used to encode a 'code_verifier' | ||
* that will be used during authorization code exchange. This parameter must | ||
* be used with the 'code_challenge' parameter. The value of the | ||
* 'code_challenge_method' defaults to "plain" if not present in the request | ||
* that includes a 'code_challenge'. The only supported values for this | ||
* parameter are "S256" or "plain". | ||
*/ | ||
code_challenge_method?: CodeChallengeMethod; | ||
/** | ||
* Recommended. Specifies an encoded 'code_verifier' that will be used as a | ||
* server-side challenge during authorization code exchange. This parameter | ||
* must be used with the 'code_challenge' parameter described above. | ||
*/ | ||
code_challenge?: string; | ||
} | ||
@@ -72,2 +181,14 @@ export interface AuthClientOpts { | ||
} | ||
export interface VerifyIdTokenOptions { | ||
idToken: string; | ||
audience: string | string[]; | ||
maxExpiry?: number; | ||
} | ||
export interface OAuth2ClientOptions { | ||
clientId?: string; | ||
clientSecret?: string; | ||
redirectUri?: string; | ||
authBaseUrl?: string; | ||
tokenUrl?: string; | ||
} | ||
export declare class OAuth2Client extends AuthClient { | ||
@@ -77,3 +198,4 @@ private redirectUri?; | ||
private certificateExpiry; | ||
protected opts: AuthClientOpts; | ||
protected authBaseUrl?: string; | ||
protected tokenUrl?: string; | ||
_clientId?: string; | ||
@@ -92,2 +214,3 @@ _clientSecret?: string; | ||
*/ | ||
constructor(options: OAuth2ClientOptions); | ||
constructor(clientId?: string, clientSecret?: string, redirectUri?: string, opts?: AuthClientOpts); | ||
@@ -129,2 +252,11 @@ /** | ||
/** | ||
* Convenience method to automatically generate a code_verifier, and it's | ||
* resulting SHA256. If used, this must be paired with a S256 | ||
* code_challenge_method. | ||
*/ | ||
generateCodeVerifier(): { | ||
codeVerifier: string; | ||
codeChallenge: string; | ||
}; | ||
/** | ||
* Gets the access token for the given code. | ||
@@ -135,4 +267,6 @@ * @param {string} code The authorization code. | ||
getToken(code: string): Promise<GetTokenResponse>; | ||
getToken(options: GetTokenOptions): Promise<GetTokenResponse>; | ||
getToken(code: string, callback: GetTokenCallback): void; | ||
private getTokenAsync(code); | ||
getToken(options: GetTokenOptions, callback: GetTokenCallback): void; | ||
private getTokenAsync(options); | ||
/** | ||
@@ -208,9 +342,8 @@ * Refreshes the access token. | ||
* 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 {VerifyIdTokenOptions} Object that contains all options. | ||
* @param {function=} callback Callback supplying GoogleLogin if successful | ||
*/ | ||
verifyIdToken(idToken: string, audience: string | string[]): Promise<LoginTicket | null>; | ||
verifyIdToken(idToken: string, audience: string | string[], callback: (err: Error | null, login?: LoginTicket | null) => void): void; | ||
private verifyIdTokenAsync(idToken, audience); | ||
verifyIdToken(options: VerifyIdTokenOptions): Promise<LoginTicket | null>; | ||
verifyIdToken(options: VerifyIdTokenOptions, callback: (err: Error | null, login?: LoginTicket | null) => void): void; | ||
private verifyIdTokenAsync(options); | ||
/** | ||
@@ -217,0 +350,0 @@ * Gets federated sign-on certificates to use for verifying identity tokens. |
@@ -63,2 +63,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var crypto = require("crypto"); | ||
var querystring = require("querystring"); | ||
@@ -68,22 +69,28 @@ var pemverifier_1 = require("./../pemverifier"); | ||
var loginticket_1 = require("./loginticket"); | ||
var CodeChallengeMethod; | ||
(function (CodeChallengeMethod) { | ||
CodeChallengeMethod["Plain"] = "plain"; | ||
CodeChallengeMethod["S256"] = "S256"; | ||
})(CodeChallengeMethod = exports.CodeChallengeMethod || (exports.CodeChallengeMethod = {})); | ||
var OAuth2Client = /** @class */ (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=} opts optional options for overriding the given parameters. | ||
* @constructor | ||
*/ | ||
function OAuth2Client(clientId, clientSecret, redirectUri, opts) { | ||
if (opts === void 0) { opts = {}; } | ||
function OAuth2Client(optionsOrClientId, clientSecret, redirectUri, authClientOpts) { | ||
if (authClientOpts === void 0) { authClientOpts = {}; } | ||
var _this = _super.call(this) || this; | ||
_this.certificateCache = null; | ||
_this.certificateExpiry = null; | ||
_this._clientId = clientId; | ||
_this._clientSecret = clientSecret; | ||
_this.redirectUri = redirectUri; | ||
_this.opts = opts; | ||
var opts = (optionsOrClientId && typeof optionsOrClientId === 'object') ? | ||
optionsOrClientId : | ||
{ | ||
clientId: optionsOrClientId, | ||
clientSecret: clientSecret, | ||
redirectUri: redirectUri, | ||
tokenUrl: authClientOpts.tokenUrl, | ||
authBaseUrl: authClientOpts.authBaseUrl | ||
}; | ||
_this._clientId = opts.clientId; | ||
_this._clientSecret = opts.clientSecret; | ||
_this.redirectUri = opts.redirectUri; | ||
_this.authBaseUrl = opts.authBaseUrl; | ||
_this.tokenUrl = opts.tokenUrl; | ||
_this.credentials = {}; | ||
@@ -99,2 +106,5 @@ return _this; | ||
if (opts === void 0) { opts = {}; } | ||
if (opts.code_challenge_method && !opts.code_challenge) { | ||
throw new Error('If a code_challenge_method is provided, code_challenge must be included.'); | ||
} | ||
opts.response_type = opts.response_type || 'code'; | ||
@@ -107,8 +117,32 @@ opts.client_id = opts.client_id || this._clientId; | ||
} | ||
var rootUrl = this.opts.authBaseUrl || OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_; | ||
var rootUrl = this.authBaseUrl || OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_; | ||
return rootUrl + '?' + querystring.stringify(opts); | ||
}; | ||
OAuth2Client.prototype.getToken = function (code, callback) { | ||
/** | ||
* Convenience method to automatically generate a code_verifier, and it's | ||
* resulting SHA256. If used, this must be paired with a S256 | ||
* code_challenge_method. | ||
*/ | ||
OAuth2Client.prototype.generateCodeVerifier = function () { | ||
// base64 encoding uses 6 bits per character, and we want to generate128 | ||
// characters. 6*128/8 = 96. | ||
var randomString = crypto.randomBytes(96).toString('base64'); | ||
// The valid characters in the code_verifier are [A-Z]/[a-z]/[0-9]/ | ||
// "-"/"."/"_"/"~". Base64 encoded strings are pretty close, so we're just | ||
// swapping out a few chars. | ||
var codeVerifier = randomString.replace(/\+/g, '~').replace(/=/g, '_').replace(/\//g, '-'); | ||
// Generate the base64 encoded SHA256 | ||
var unencodedCodeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64'); | ||
// We need to use base64UrlEncoding instead of standard base64 | ||
var codeChallenge = unencodedCodeChallenge.split('=')[0] | ||
.replace(/\+/g, '-') | ||
.replace(/\//g, '_'); | ||
return { codeVerifier: codeVerifier, codeChallenge: codeChallenge }; | ||
}; | ||
OAuth2Client.prototype.getToken = function (codeOrOptions, callback) { | ||
var options = (typeof codeOrOptions === 'string') ? | ||
{ code: codeOrOptions } : | ||
codeOrOptions; | ||
if (callback) { | ||
this.getTokenAsync(code) | ||
this.getTokenAsync(options) | ||
.then(function (r) { return callback(null, r.tokens, r.res); }) | ||
@@ -118,6 +152,6 @@ .catch(function (e) { return callback(e, null, e.response); }); | ||
else { | ||
return this.getTokenAsync(code); | ||
return this.getTokenAsync(options); | ||
} | ||
}; | ||
OAuth2Client.prototype.getTokenAsync = function (code) { | ||
OAuth2Client.prototype.getTokenAsync = function (options) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -128,9 +162,10 @@ var url, values, res, tokens; | ||
case 0: | ||
url = this.opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; | ||
url = this.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; | ||
values = { | ||
code: code, | ||
code: options.code, | ||
client_id: this._clientId, | ||
client_secret: this._clientSecret, | ||
redirect_uri: this.redirectUri, | ||
grant_type: 'authorization_code' | ||
grant_type: 'authorization_code', | ||
code_verifier: options.codeVerifier | ||
}; | ||
@@ -168,3 +203,3 @@ return [4 /*yield*/, this.transporter.request({ | ||
case 0: | ||
url = this.opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; | ||
url = this.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; | ||
data = { | ||
@@ -427,5 +462,11 @@ refresh_token: refreshToken, | ||
}; | ||
OAuth2Client.prototype.verifyIdToken = function (idToken, audience, callback) { | ||
OAuth2Client.prototype.verifyIdToken = function (options, callback) { | ||
// This function used to accept two arguments instead of an options object. | ||
// Check the types to help users upgrade with less pain. | ||
// This check can be removed after a 2.0 release. | ||
if (callback && typeof callback !== 'function') { | ||
throw new Error('This method accepts an options object as the first parameter, which includes the idToken, audience, and maxExpiry.'); | ||
} | ||
if (callback) { | ||
this.verifyIdTokenAsync(idToken, audience) | ||
this.verifyIdTokenAsync(options) | ||
.then(function (r) { return callback(null, r); }) | ||
@@ -435,12 +476,12 @@ .catch(callback); | ||
else { | ||
return this.verifyIdTokenAsync(idToken, audience); | ||
return this.verifyIdTokenAsync(options); | ||
} | ||
}; | ||
OAuth2Client.prototype.verifyIdTokenAsync = function (idToken, audience) { | ||
OAuth2Client.prototype.verifyIdTokenAsync = function (options) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var certs, login; | ||
var response, login; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!idToken) { | ||
if (!options.idToken) { | ||
throw new Error('The verifyIdToken method requires an ID Token'); | ||
@@ -450,4 +491,4 @@ } | ||
case 1: | ||
certs = _a.sent(); | ||
login = this.verifySignedJwtWithCerts(idToken, certs, audience, OAuth2Client.ISSUERS_); | ||
response = _a.sent(); | ||
login = this.verifySignedJwtWithCerts(options.idToken, response.certs, options.audience, OAuth2Client.ISSUERS_, options.maxExpiry); | ||
return [2 /*return*/, login]; | ||
@@ -621,7 +662,7 @@ } | ||
*/ | ||
OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_ = 'https://accounts.google.com/o/oauth2/auth'; | ||
OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_ = 'https://accounts.google.com/o/oauth2/v2/auth'; | ||
/** | ||
* The base endpoint for token retrieval. | ||
*/ | ||
OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_ = 'https://accounts.google.com/o/oauth2/token'; | ||
OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_ = 'https://www.googleapis.com/oauth2/v4/token'; | ||
/** | ||
@@ -628,0 +669,0 @@ * The base endpoint to revoke tokens. |
@@ -21,4 +21,4 @@ /** | ||
export { JWT } from './auth/jwtclient'; | ||
export { OAuth2Client } from './auth/oauth2client'; | ||
export { CodeChallengeMethod, OAuth2Client } from './auth/oauth2client'; | ||
export { UserRefreshClient } from './auth/refreshclient'; | ||
export { DefaultTransporter } from './transporters'; |
@@ -29,2 +29,3 @@ "use strict"; | ||
var oauth2client_1 = require("./auth/oauth2client"); | ||
exports.CodeChallengeMethod = oauth2client_1.CodeChallengeMethod; | ||
exports.OAuth2Client = oauth2client_1.OAuth2Client; | ||
@@ -31,0 +32,0 @@ var refreshclient_1 = require("./auth/refreshclient"); |
{ | ||
"name": "google-auth-library", | ||
"version": "1.0.0-alpha.1", | ||
"version": "1.0.0", | ||
"author": "Google Inc.", | ||
@@ -23,4 +23,4 @@ "description": "Google APIs Authentication Client Library for Node.js", | ||
"dependencies": { | ||
"axios": "^0.17.1", | ||
"gtoken": "^2.0.2", | ||
"axios": "^0.17.1", | ||
"jws": "^3.1.4", | ||
@@ -30,21 +30,27 @@ "lodash.isstring": "^4.0.1" | ||
"devDependencies": { | ||
"@justinbeckwith/typedoc": "^0.10.1", | ||
"@types/jws": "^3.1.0", | ||
"@types/lodash.isstring": "^4.0.2", | ||
"@types/mocha": "^2.2.41", | ||
"@types/lodash.isstring": "^4.0.3", | ||
"@types/mocha": "^2.2.45", | ||
"@types/ncp": "^2.0.1", | ||
"@types/nock": "^8.2.1", | ||
"@types/node": "^8.0.47", | ||
"@types/nock": "^9.1.1", | ||
"@types/node": "^9.3.0", | ||
"@types/pify": "^3.0.0", | ||
"@types/tmp": "0.0.33", | ||
"coveralls": "^2.13.0", | ||
"gts": "^0.5.1", | ||
"clang-format": "^1.0.50", | ||
"coveralls": "^3.0.0", | ||
"gh-pages": "^1.1.0", | ||
"gts": "^0.5.3", | ||
"istanbul": "^0.4.5", | ||
"keypair": "^1.0.0", | ||
"mocha": "^3.2.0", | ||
"js-green-licenses": "^0.2.0", | ||
"keypair": "^1.0.1", | ||
"mocha": "^4.1.0", | ||
"ncp": "^2.0.0", | ||
"nock": "^9.0.2", | ||
"nock": "^9.1.5", | ||
"opn": "^5.1.0", | ||
"pify": "^3.0.0", | ||
"source-map-support": "^0.4.14", | ||
"prettier": "^1.9.2", | ||
"source-map-support": "^0.5.0", | ||
"tmp": "0.0.33", | ||
"typescript": "~2.6.0" | ||
"typescript": "~2.6.2" | ||
}, | ||
@@ -65,7 +71,11 @@ "files": [ | ||
"compile": "tsc -p .", | ||
"fix": "gts fix", | ||
"fix": "gts fix && npm run fix-samples", | ||
"fix-samples": "prettier --write --single-quote examples/*.js", | ||
"pretest": "npm run compile", | ||
"posttest": "npm run check" | ||
"posttest": "npm run check && npm run license-check", | ||
"license-check": "jsgl --local .", | ||
"generate-docs": "typedoc --excludePrivate --excludeExternals --mode modules --out docs src && touch docs/.nojekyll", | ||
"publish-docs": "gh-pages --dotfiles --dist docs --remote upstream" | ||
}, | ||
"license": "Apache-2.0" | ||
} |
379
README.md
@@ -1,41 +0,38 @@ | ||
# Google APIs Node.js Client | ||
<img src="https://avatars0.githubusercontent.com/u/1342004?v=3&s=96" alt="Google Inc. logo" title="Google" align="right" height="96" width="96"/> | ||
# Google Auth Library | ||
[![Greenkeeper badge][greenkeeperimg]][greenkeeper] | ||
[![npm version][npmimg]][npm] | ||
[![Build Status][travisimg]][travis] | ||
[![Code Coverage][coverallsimg]][coveralls] | ||
[![Dependencies][david-dm-img]][david-dm] | ||
[![Known Vulnerabilities][snyk-image]][snyk-url] | ||
This is Google's officially supported [node.js][node] client library for using | ||
OAuth 2.0 authorization and authentication with Google APIs. | ||
This is Google's officially supported [node.js][node] client library for using OAuth 2.0 authorization and authentication with Google APIs. | ||
### Questions/problems? | ||
* Ask your development related questions on [![Ask a question on Stackoverflow][overflowimg]][stackoverflow] | ||
* If you've found an bug/issue, please [file it on GitHub][bugs]. | ||
## Installation | ||
This library is distributed on `npm`. To add it as a dependency, run the following command: | ||
This library is distributed on `npm`. To add it as a dependency, | ||
run the following command: | ||
``` sh | ||
$ npm install google-auth-library --save | ||
$ npm install google-auth-library | ||
``` | ||
## Upgrading to 1.x | ||
The `1.x` release includes a variety of bug fixes, new features, and breaking changes. Please take care, and see [the release notes](https://github.com/google/google-auth-library-nodejs/releases/tag/1.0.0-alpha.1) for a list of breaking changes, and the upgrade guide. | ||
## Ways to authenticate | ||
This library provides a variety of ways to authenticate to your Google services. | ||
- [Application Default Credentials](#choosing-the-correct-credential-type-automatically) - Use Application Default Credentials when you use a single identity for all users in your application. Especially useful for applications running on Google Cloud. | ||
- [OAuth 2](#oauth2-client) - Use OAuth2 when you need to perform actions on behalf of the end user. | ||
- [JSON Web Tokens](#using-json-web-tokens) - Use JWT when you are using a single identity for all users. Especially useful for server->server or server->API communication. | ||
## 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 in calling Google APIs. | ||
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 level for the application independent of the user. This is the recommended approach to authorize calls to Cloud APIs, particularly when you're building an application that uses Google Cloud Platform. | ||
They are best suited for cases when the call needs to have the same identity and authorization | ||
level for the application independent of the user. This is the recommended approach to authorize | ||
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][devconsole] and select | ||
**Service account** from the **Add credentials** dropdown. | ||
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][devconsole] and select **Service account** from the **Add credentials** dropdown. | ||
@@ -45,58 +42,273 @@ > This file is your *only copy* of these credentials. It should never be | ||
Once downloaded, store the path to this file in the | ||
`GOOGLE_APPLICATION_CREDENTIALS` environment variable. | ||
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][devconsole] and enable the APIs you'd like to | ||
call. For the example below, you must enable the `DNS API`. | ||
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][devconsole] 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. | ||
#### Choosing the correct credential type automatically | ||
Rather than manually creating an OAuth2 client, JWT client, or Compute client, the auth library can create the correct credential type for you, depending upon the environment your code is running under. | ||
For example, a JWT auth client will be created when your code is running on your local developer machine, and a Compute client will be created when the same code is running on Google Cloud Platform. | ||
The code below shows how to retrieve a default credential type, depending upon the runtime environment. The createScopedRequired must be called to determine when you need to pass in the scopes manually, and when they have been set for you automatically based on the configured runtime environment. | ||
```js | ||
var google = require('googleapis'); | ||
var GoogleAuth = require('google-auth-library').GoogleAuth; | ||
const {GoogleAuth} = require('google-auth-library'); | ||
const auth = new GoogleAuth(); | ||
var authFactory = new GoogleAuth(); | ||
var dns = google.dns('v1'); | ||
/** | ||
* Acquire a client, and make a request to an API that's enabled by default. | ||
*/ | ||
async function main() { | ||
try { | ||
const adc = await getADC(); | ||
const url = `https://www.googleapis.com/dns/v1/projects/${adc.projectId}`; | ||
const res = await adc.client.request({url}); | ||
console.log(res.data); | ||
} catch (e) { | ||
console.error('Error making request.'); | ||
console.error(e); | ||
} | ||
} | ||
authFactory.getApplicationDefault(function(err, authClient) { | ||
if (err) { | ||
console.log('Authentication failed because of ', err); | ||
return; | ||
/** | ||
* Instead of specifying the type of client you'd like to use (JWT, OAuth2, etc) | ||
* this library will automatically choose the right client based on the environment. | ||
*/ | ||
async function getADC() { | ||
// Acquire a client and the projectId based on the environment. This method looks | ||
// for the GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS environment variables. | ||
const res = await auth.getApplicationDefault(); | ||
let client = res.credential; | ||
// The createScopedRequired method returns true when running on GAE or a local developer | ||
// machine. In that case, the desired scopes must be passed in manually. When the code is | ||
// running in GCE or a Managed VM, the scopes are pulled from the GCE metadata server. | ||
// See https://cloud.google.com/compute/docs/authentication for more information. | ||
if (client.createScopedRequired && client.createScopedRequired()) { | ||
// Scopes can be specified either as an array or as a single, space-delimited string. | ||
const scopes = ['https://www.googleapis.com/auth/cloud-platform']; | ||
client = client.createScoped(scopes); | ||
} | ||
if (authClient.createScopedRequired && authClient.createScopedRequired()) { | ||
var scopes = ['https://www.googleapis.com/auth/cloud-platform']; | ||
authClient = authClient.createScoped(scopes); | ||
return { | ||
client: client, | ||
projectId: res.projectId | ||
} | ||
} | ||
var request = { | ||
// TODO: Change placeholders below to values for parameters to the 'get' method: | ||
main(); | ||
``` | ||
// 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 | ||
}; | ||
#### OAuth2 client | ||
dns.changes.get(request, function(err, result) { | ||
if (err) { | ||
console.log(err); | ||
} else { | ||
console.log(result); | ||
} | ||
This client comes with an [OAuth2][oauth] client that allows you to retrieve an access token and refreshes the token and retry the request seamlessly if you also provide an `expiry_date` and the token is expired. The basics of Google's OAuth2 implementation is explained on [Google Authorization and Authentication documentation][authdocs]. | ||
In the following examples, you may need a `CLIENT_ID`, `CLIENT_SECRET` and `REDIRECT_URL`. You can find these pieces of information by going to the [Developer Console][devconsole], clicking your project > APIs & auth > credentials. | ||
For more information about OAuth2 and how it works, [see here][oauth]. | ||
##### A complete OAuth2 example | ||
Let's take a look at a complete example. | ||
``` js | ||
const {OAuth2Client} = require('google-auth-library'); | ||
const http = require('http'); | ||
const url = require('url'); | ||
const querystring = require('querystring'); | ||
const opn = require('opn'); | ||
// Download your OAuth2 configuration from the Google | ||
const keys = require('./keys.json'); | ||
/** | ||
* Start by acquiring a pre-authenticated oAuth2 client. | ||
*/ | ||
async function main() { | ||
try { | ||
const oAuth2Client = await getAuthenticatedClient(); | ||
// Make a simple request to the Google Plus API using our pre-authenticated client. The `request()` method | ||
// takes an AxiosRequestConfig object. Visit https://github.com/axios/axios#request-config. | ||
const url = 'https://www.googleapis.com/plus/v1/people?query=pizza'; | ||
const res = await oAuth2Client.request({url}) | ||
console.log(res.data); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
process.exit(); | ||
} | ||
/** | ||
* Create a new OAuth2Client, and go through the OAuth2 content | ||
* workflow. Return the full client to the callback. | ||
*/ | ||
function getAuthenticatedClient() { | ||
return new Promise((resolve, reject) => { | ||
// create an oAuth client to authorize the API call. Secrets are kept in a `keys.json` file, | ||
// which should be downloaded from the Google Developers Console. | ||
const oAuth2Client = new OAuth2Client( | ||
keys.web.client_id, | ||
keys.web.client_secret, | ||
keys.web.redirect_uris[0] | ||
); | ||
// Generate the url that will be used for the consent dialog. | ||
const authorizeUrl = oAuth2Client.generateAuthUrl({ | ||
access_type: 'offline', | ||
scope: 'https://www.googleapis.com/auth/plus.me' | ||
}); | ||
// Open an http server to accept the oauth callback. In this simple example, the | ||
// only request to our webserver is to /oauth2callback?code=<code> | ||
const server = http.createServer(async (req, res) => { | ||
if (req.url.indexOf('/oauth2callback') > -1) { | ||
// acquire the code from the querystring, and close the web server. | ||
const qs = querystring.parse(url.parse(req.url).query); | ||
console.log(`Code is ${qs.code}`); | ||
res.end('Authentication successful! Please return to the console.'); | ||
server.close(); | ||
// Now that we have the code, use that to acquire tokens. | ||
const r = await oAuth2Client.getToken(qs.code) | ||
// Make sure to set the credentials on the OAuth2 client. | ||
oAuth2Client.setCredentials(r.tokens); | ||
console.info('Tokens acquired.'); | ||
resolve(oAuth2Client); | ||
} | ||
}).listen(3000, () => { | ||
// open the browser to the authorize url to start the workflow | ||
opn(authorizeUrl); | ||
}); | ||
}); | ||
} | ||
main(); | ||
``` | ||
##### IMPORTANT NOTE | ||
`refresh_token` is only returned on the first authorization. | ||
More details [here](https://github.com/google/google-api-nodejs-client/issues/750#issuecomment-304521450) | ||
##### Retrieve access token | ||
With the code returned, you can ask for an access token as shown below: | ||
``` js | ||
const tokens = await oauth2Client.getToken(code); | ||
// Now tokens contains an access_token and an optional refresh_token. Save them. | ||
oauth2Client.setCredentials(tokens); | ||
``` | ||
##### Manually refreshing access token | ||
If you need to manually refresh the `access_token` associated with your OAuth2 client, ensure the call to `generateAuthUrl` sets the `access_type` to `offline`. The refresh token will only be returned for the first authorization by the user. To force consent, set the `prompt` property to `consent`: | ||
```js | ||
// Generate the url that will be used for the consent dialog. | ||
const authorizeUrl = oAuth2Client.generateAuthUrl({ | ||
// To get a refresh token, you MUST set access_type to `offline`. | ||
access_type: 'offline', | ||
// set the appropriate scopes | ||
scope: 'https://www.googleapis.com/auth/plus.me', | ||
// A refresh token is only returned the first time the user | ||
// consents to providing access. For illustration purposes, | ||
// setting the prompt to 'consent' will force this consent | ||
// every time, forcing a refresh_token to be returned. | ||
prompt: 'consent' | ||
}); | ||
``` | ||
If a refresh_token is set again on `OAuth2Client.credentials.refresh_token`, you can can `refreshAccessToken()`: | ||
``` js | ||
const tokens = await oauth2Client.refreshAccessToken(); | ||
// your access_token is now refreshed and stored in oauth2Client | ||
// store these new tokens in a safe place (e.g. database) | ||
``` | ||
#### Using JSON Web Tokens | ||
The Google Developers Console provides `.json` file that you can use to configure a JWT auth client and authenticate your requests, for example when using a service account. | ||
``` js | ||
const {JWT} = require('../build/src/index'); | ||
const keys = require('./jwt.keys.json'); | ||
async function main() { | ||
const client = new JWT( | ||
keys.client_email, | ||
null, | ||
keys.private_key, | ||
['https://www.googleapis.com/auth/cloud-platform'], | ||
); | ||
await client.authorize(); | ||
const url = `https://www.googleapis.com/dns/v1/projects/${keys.project_id}`; | ||
const res = await client.request({url}); | ||
console.log(res.data); | ||
} | ||
main().catch(console.error); | ||
``` | ||
The parameters for the JWT auth client including how to use it with a `.pem` file are explained in [samples/jwt.js](samples/jwt.js). | ||
#### Loading credentials from environment variables | ||
Instead of loading credentials from a key file, you can also provide them using an environment variable and the `GoogleAuth.fromJSON()` method. This is particularly convenient for systems that deploy directly from source control (Heroku, App Engine, etc). | ||
Start by exporting your credentials: | ||
``` | ||
$ export CREDS='{ | ||
"type": "service_account", | ||
"project_id": "your-project-id", | ||
"private_key_id": "your-private-key-id", | ||
"private_key": "your-private-key", | ||
"client_email": "your-client-email", | ||
"client_id": "your-client-id", | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://accounts.google.com/o/oauth2/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": "your-cert-url" | ||
}' | ||
``` | ||
Now you can create a new client from the credentials: | ||
```js | ||
const {GoogleAuth} = require('google-auth-library'); | ||
// load the environment variable with our keys | ||
const keysEnvVar = process.env['CREDS']; | ||
if (!keysEnvVar) { | ||
throw new Error('The $CREDS environment variable was not found!'); | ||
} | ||
const keys = JSON.parse(keysEnvVar); | ||
async function main() { | ||
const auth = new GoogleAuth(); | ||
// load the JWT or UserRefreshClient from the keys | ||
const client = auth.fromJSON(keys); | ||
client.scopes = ['https://www.googleapis.com/auth/cloud-platform']; | ||
await client.authorize(); | ||
const url = `https://www.googleapis.com/dns/v1/projects/${keys.project_id}`; | ||
const res = await client.request({url}); | ||
console.log(res.data); | ||
} | ||
main().catch(console.error); | ||
``` | ||
#### Using a Proxy | ||
You can use the following environment variables to proxy HTTP and HTTPS requests: | ||
- HTTP_PROXY / http_proxy | ||
- HTTPS_PROXY / https_proxy | ||
When HTTP_PROXY / http_proxy are set, they will be used to proxy non-SSL requests that do not have an explicit proxy configuration option present. Similarly, HTTPS_PROXY / https_proxy will be respected for SSL requests that do not have an explicit proxy configuration option. It is valid to define a proxy in one of the environment variables, but then override it for a specific request, using the proxy configuration option. | ||
### Questions/problems? | ||
* Ask your development related questions on [![Ask a question on Stackoverflow][overflowimg]][stackoverflow] | ||
* If you've found an bug/issue, please [file it on GitHub][bugs]. | ||
## Contributing | ||
@@ -108,21 +320,32 @@ | ||
This library is licensed under Apache 2.0. Full license text is | ||
available in [LICENSE][copying]. | ||
This library is licensed under Apache 2.0. Full license text is available in [LICENSE][copying]. | ||
[travisimg]: https://api.travis-ci.org/google/google-auth-library-nodejs.svg | ||
[apiexplorer]: https://developers.google.com/apis-explorer | ||
[Application Default Credentials]: https://developers.google.com/identity/protocols/application-default-credentials#callingnode | ||
[authdocs]: https://developers.google.com/accounts/docs/OAuth2Login | ||
[axios]: https://github.com/axios/axios | ||
[axiosOpts]: https://github.com/axios/axios#request-config | ||
[bugs]: https://github.com/google/google-auth-library-nodejs/issues | ||
[contributing]: https://github.com/google/google-auth-library-nodejs/blob/master/.github/CONTRIBUTING.md | ||
[copying]: https://github.com/google/google-auth-library-nodejs/tree/master/LICENSE | ||
[coveralls]: https://coveralls.io/r/google/google-auth-library-nodejs?branch=master | ||
[coverallsimg]: https://img.shields.io/coveralls/google/google-auth-library-nodejs.svg | ||
[david-dm-img]: https://david-dm.org/google/google-auth-library-nodejs/status.svg | ||
[david-dm]: https://david-dm.org/google/google-auth-library-nodejs | ||
[greenkeeperimg]: https://badges.greenkeeper.io/google/google-auth-library-nodejs.svg | ||
[greenkeeper]: https://greenkeeper.io/ | ||
[node]: http://nodejs.org/ | ||
[npmimg]: https://img.shields.io/npm/v/google-auth-library.svg | ||
[npm]: https://www.npmjs.org/package/google-auth-library | ||
[oauth]: https://developers.google.com/identity/protocols/OAuth2 | ||
[overflowimg]: https://googledrive.com/host/0ByfSjdPVs9MZbkhjeUhMYzRTeEE/stackoveflow-tag.png | ||
[snyk-image]: https://snyk.io/test/github/google/google-auth-library-nodejs/badge.svg | ||
[snyk-url]: https://snyk.io/test/github/google/google-auth-library-nodejs | ||
[stability]: http://nodejs.org/api/stream.html#stream_stream | ||
[stackoverflow]: http://stackoverflow.com/questions/tagged/google-auth-library-nodejs | ||
[stream]: http://nodejs.org/api/stream.html#stream_class_stream_readable | ||
[travisimg]: https://api.travis-ci.org/google/google-auth-library-nodejs.svg | ||
[travis]: https://travis-ci.org/google/google-auth-library-nodejs | ||
[stackoverflow]: http://stackoverflow.com/questions/tagged/google-auth-library-nodejs | ||
[apiexplorer]: https://developers.google.com/apis-explorer | ||
[urlshort]: https://developers.google.com/url-shortener/ | ||
[usingkeys]: https://developers.google.com/console/help/#UsingKeys | ||
[contributing]: https://github.com/google/google-auth-library-nodejs/blob/master/.github/CONTRIBUTING.md | ||
[copying]: https://github.com/google/google-auth-library-nodejs/tree/master/LICENSE | ||
[authdocs]: https://developers.google.com/accounts/docs/OAuth2Login | ||
[request]: https://github.com/mikeal/request | ||
[requestopts]: https://github.com/mikeal/request#requestoptions-callback | ||
[stream]: http://nodejs.org/api/stream.html#stream_class_stream_readable | ||
[stability]: http://nodejs.org/api/stream.html#stream_stream | ||
[overflowimg]: https://googledrive.com/host/0ByfSjdPVs9MZbkhjeUhMYzRTeEE/stackoveflow-tag.png | ||
[devconsole]: https://console.developer.google.com | ||
@@ -133,6 +356,2 @@ [oauth]: https://developers.google.com/accounts/docs/OAuth2 | ||
[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 | ||
[david-dm-img]: https://david-dm.org/google/google-auth-library-nodejs/status.svg | ||
[david-dm]: https://david-dm.org/google/google-auth-library-nodejs | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
234985
3596
1
355
1
25