Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / google-auth-library / build / src / auth / oauth2client.js
diff --git a/legacy-libs/google-auth-library/build/src/auth/oauth2client.js b/legacy-libs/google-auth-library/build/src/auth/oauth2client.js
new file mode 100644 (file)
index 0000000..dce8a46
--- /dev/null
@@ -0,0 +1,665 @@
+"use strict";
+/**
+ * Copyright 2019 Google LLC. 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.
+ */
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const querystring = require("querystring");
+const stream = require("stream");
+const crypto_1 = require("../crypto/crypto");
+const isbrowser_1 = require("../isbrowser");
+const messages = require("../messages");
+const authclient_1 = require("./authclient");
+const loginticket_1 = require("./loginticket");
+var CodeChallengeMethod;
+(function (CodeChallengeMethod) {
+    CodeChallengeMethod["Plain"] = "plain";
+    CodeChallengeMethod["S256"] = "S256";
+})(CodeChallengeMethod = exports.CodeChallengeMethod || (exports.CodeChallengeMethod = {}));
+var CertificateFormat;
+(function (CertificateFormat) {
+    CertificateFormat["PEM"] = "PEM";
+    CertificateFormat["JWK"] = "JWK";
+})(CertificateFormat = exports.CertificateFormat || (exports.CertificateFormat = {}));
+class OAuth2Client extends authclient_1.AuthClient {
+    constructor(optionsOrClientId, clientSecret, redirectUri) {
+        super();
+        this.certificateCache = {};
+        this.certificateExpiry = null;
+        this.certificateCacheFormat = CertificateFormat.PEM;
+        this.refreshTokenPromises = new Map();
+        const opts = (optionsOrClientId && typeof optionsOrClientId === 'object') ?
+            optionsOrClientId :
+            { clientId: optionsOrClientId, clientSecret, redirectUri };
+        this._clientId = opts.clientId;
+        this._clientSecret = opts.clientSecret;
+        this.redirectUri = opts.redirectUri;
+        this.eagerRefreshThresholdMillis =
+            opts.eagerRefreshThresholdMillis || 5 * 60 * 1000;
+    }
+    /**
+     * Generates URL for consent page landing.
+     * @param opts Options.
+     * @return URL to consent page.
+     */
+    generateAuthUrl(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';
+        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(' ');
+        }
+        const rootUrl = OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_;
+        return rootUrl + '?' + querystring.stringify(opts);
+    }
+    generateCodeVerifier() {
+        // To make the code compatible with browser SubtleCrypto we need to make
+        // this method async.
+        throw new Error('generateCodeVerifier is removed, please use generateCodeVerifierAsync instead.');
+    }
+    /**
+     * 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.
+     */
+    generateCodeVerifierAsync() {
+        return __awaiter(this, void 0, void 0, function* () {
+            // base64 encoding uses 6 bits per character, and we want to generate128
+            // characters. 6*128/8 = 96.
+            const crypto = crypto_1.createCrypto();
+            const randomString = crypto.randomBytesBase64(96);
+            // 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.
+            const codeVerifier = randomString.replace(/\+/g, '~').replace(/=/g, '_').replace(/\//g, '-');
+            // Generate the base64 encoded SHA256
+            const unencodedCodeChallenge = yield crypto.sha256DigestBase64(codeVerifier);
+            // We need to use base64UrlEncoding instead of standard base64
+            const codeChallenge = unencodedCodeChallenge.split('=')[0]
+                .replace(/\+/g, '-')
+                .replace(/\//g, '_');
+            return { codeVerifier, codeChallenge };
+        });
+    }
+    getToken(codeOrOptions, callback) {
+        const options = (typeof codeOrOptions === 'string') ?
+            { code: codeOrOptions } :
+            codeOrOptions;
+        if (callback) {
+            this.getTokenAsync(options).then(r => callback(null, r.tokens, r.res), e => callback(e, null, e.response));
+        }
+        else {
+            return this.getTokenAsync(options);
+        }
+    }
+    getTokenAsync(options) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const url = OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_;
+            const values = {
+                code: options.code,
+                client_id: options.client_id || this._clientId,
+                client_secret: this._clientSecret,
+                redirect_uri: options.redirect_uri || this.redirectUri,
+                grant_type: 'authorization_code',
+                code_verifier: options.codeVerifier
+            };
+            const res = yield this.transporter.request({
+                method: 'POST',
+                url,
+                data: querystring.stringify(values),
+                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+            });
+            const tokens = res.data;
+            if (res.data && res.data.expires_in) {
+                tokens.expiry_date =
+                    ((new Date()).getTime() + (res.data.expires_in * 1000));
+                delete tokens.expires_in;
+            }
+            this.emit('tokens', tokens);
+            return { tokens, res };
+        });
+    }
+    /**
+     * Refreshes the access token.
+     * @param refresh_token Existing refresh token.
+     * @private
+     */
+    refreshToken(refreshToken) {
+        return __awaiter(this, void 0, void 0, function* () {
+            if (!refreshToken) {
+                return this.refreshTokenNoCache(refreshToken);
+            }
+            // If a request to refresh using the same token has started,
+            // return the same promise.
+            if (this.refreshTokenPromises.has(refreshToken)) {
+                return this.refreshTokenPromises.get(refreshToken);
+            }
+            const p = this.refreshTokenNoCache(refreshToken)
+                .then(r => {
+                this.refreshTokenPromises.delete(refreshToken);
+                return r;
+            }, e => {
+                this.refreshTokenPromises.delete(refreshToken);
+                throw e;
+            });
+            this.refreshTokenPromises.set(refreshToken, p);
+            return p;
+        });
+    }
+    refreshTokenNoCache(refreshToken) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const url = OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_;
+            const data = {
+                refresh_token: refreshToken,
+                client_id: this._clientId,
+                client_secret: this._clientSecret,
+                grant_type: 'refresh_token'
+            };
+            // request for new token
+            const res = yield this.transporter.request({
+                method: 'POST',
+                url,
+                data: querystring.stringify(data),
+                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+            });
+            const tokens = res.data;
+            // TODO: de-duplicate this code from a few spots
+            if (res.data && res.data.expires_in) {
+                tokens.expiry_date =
+                    ((new Date()).getTime() + (res.data.expires_in * 1000));
+                delete tokens.expires_in;
+            }
+            this.emit('tokens', tokens);
+            return { tokens, res };
+        });
+    }
+    refreshAccessToken(callback) {
+        messages.warn(messages.REFRESH_ACCESS_TOKEN_DEPRECATED);
+        if (callback) {
+            this.refreshAccessTokenAsync().then(r => callback(null, r.credentials, r.res), callback);
+        }
+        else {
+            return this.refreshAccessTokenAsync();
+        }
+    }
+    refreshAccessTokenAsync() {
+        return __awaiter(this, void 0, void 0, function* () {
+            if (!this.credentials.refresh_token) {
+                throw new Error('No refresh token is set.');
+            }
+            const r = yield this.refreshToken(this.credentials.refresh_token);
+            const tokens = r.tokens;
+            tokens.refresh_token = this.credentials.refresh_token;
+            this.credentials = tokens;
+            return { credentials: this.credentials, res: r.res };
+        });
+    }
+    getAccessToken(callback) {
+        if (callback) {
+            this.getAccessTokenAsync().then(r => callback(null, r.token, r.res), callback);
+        }
+        else {
+            return this.getAccessTokenAsync();
+        }
+    }
+    getAccessTokenAsync() {
+        return __awaiter(this, void 0, void 0, function* () {
+            const shouldRefresh = !this.credentials.access_token || this.isTokenExpiring();
+            if (shouldRefresh) {
+                if (!this.credentials.refresh_token) {
+                    throw new Error('No refresh token is set.');
+                }
+                const r = yield this.refreshAccessTokenAsync();
+                if (!r.credentials || (r.credentials && !r.credentials.access_token)) {
+                    throw new Error('Could not refresh access token.');
+                }
+                return { token: r.credentials.access_token, res: r.res };
+            }
+            else {
+                return { token: this.credentials.access_token };
+            }
+        });
+    }
+    getRequestMetadata(url, callback) {
+        messages.warn(messages.OAUTH_GET_REQUEST_METADATA_DEPRECATED);
+        if (callback) {
+            this.getRequestMetadataAsync(url).then(r => callback(null, r.headers, r.res), callback);
+        }
+        else {
+            return this.getRequestMetadataAsync();
+        }
+    }
+    /**
+     * The main authentication interface.  It takes an optional url which when
+     * present is the endpoint being accessed, and returns a Promise which
+     * resolves with authorization header fields.
+     *
+     * In OAuth2Client, the result has the form:
+     * { Authorization: 'Bearer <access_token_value>' }
+     * @param url The optional url being authorized
+     */
+    getRequestHeaders(url) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const res = yield this.getRequestMetadataAsync(url);
+            return res.headers;
+        });
+    }
+    getRequestMetadataAsync(url) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const thisCreds = this.credentials;
+            if (!thisCreds.access_token && !thisCreds.refresh_token && !this.apiKey) {
+                throw new Error('No access, refresh token or API key is set.');
+            }
+            if (thisCreds.access_token && !this.isTokenExpiring()) {
+                thisCreds.token_type = thisCreds.token_type || 'Bearer';
+                const headers = {
+                    Authorization: thisCreds.token_type + ' ' + thisCreds.access_token
+                };
+                return { headers };
+            }
+            if (this.apiKey) {
+                return { headers: {} };
+            }
+            let r = null;
+            let tokens = null;
+            try {
+                r = yield this.refreshToken(thisCreds.refresh_token);
+                tokens = r.tokens;
+            }
+            catch (err) {
+                const e = err;
+                if (e.response &&
+                    (e.response.status === 403 || e.response.status === 404)) {
+                    e.message = 'Could not refresh access token.';
+                }
+                throw e;
+            }
+            const credentials = this.credentials;
+            credentials.token_type = credentials.token_type || 'Bearer';
+            tokens.refresh_token = credentials.refresh_token;
+            this.credentials = tokens;
+            const headers = {
+                Authorization: credentials.token_type + ' ' + tokens.access_token
+            };
+            return { headers, res: r.res };
+        });
+    }
+    /**
+     * Generates an URL to revoke the given token.
+     * @param token The existing token to be revoked.
+     */
+    static getRevokeTokenUrl(token) {
+        const parameters = querystring.stringify({ token });
+        return `${OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_}?${parameters}`;
+    }
+    revokeToken(token, callback) {
+        const opts = {
+            url: OAuth2Client.getRevokeTokenUrl(token),
+            method: 'POST'
+        };
+        if (callback) {
+            this.transporter.request(opts).then(r => callback(null, r), callback);
+        }
+        else {
+            return this.transporter.request(opts);
+        }
+    }
+    revokeCredentials(callback) {
+        if (callback) {
+            this.revokeCredentialsAsync().then(res => callback(null, res), callback);
+        }
+        else {
+            return this.revokeCredentialsAsync();
+        }
+    }
+    revokeCredentialsAsync() {
+        return __awaiter(this, void 0, void 0, function* () {
+            const token = this.credentials.access_token;
+            this.credentials = {};
+            if (token) {
+                return this.revokeToken(token);
+            }
+            else {
+                throw new Error('No access token to revoke.');
+            }
+        });
+    }
+    request(opts, callback) {
+        if (callback) {
+            this.requestAsync(opts).then(r => callback(null, r), e => {
+                return callback(e, e.response);
+            });
+        }
+        else {
+            return this.requestAsync(opts);
+        }
+    }
+    requestAsync(opts, retry = false) {
+        return __awaiter(this, void 0, void 0, function* () {
+            let r2;
+            try {
+                const r = yield this.getRequestMetadataAsync(opts.url);
+                if (r.headers && r.headers.Authorization) {
+                    opts.headers = opts.headers || {};
+                    opts.headers.Authorization = r.headers.Authorization;
+                }
+                if (this.apiKey) {
+                    opts.params = Object.assign(opts.params || {}, { key: this.apiKey });
+                }
+                r2 = yield this.transporter.request(opts);
+            }
+            catch (e) {
+                const res = e.response;
+                if (res) {
+                    const statusCode = res.status;
+                    // Retry the request for metadata if the following criteria are true:
+                    // - We haven't already retried.  It only makes sense to retry once.
+                    // - The response was a 401 or a 403
+                    // - The request didn't send a readableStream
+                    // - An access_token and refresh_token were available, but no
+                    //   expiry_date was availabe. This can happen when developers stash
+                    //   the access_token and refresh_token for later use, but the
+                    //   access_token fails on the first try because it's expired.
+                    const mayRequireRefresh = this.credentials &&
+                        this.credentials.access_token && this.credentials.refresh_token &&
+                        !this.credentials.expiry_date;
+                    const isReadableStream = res.config.data instanceof stream.Readable;
+                    const isAuthErr = statusCode === 401 || statusCode === 403;
+                    if (!retry && isAuthErr && !isReadableStream && mayRequireRefresh) {
+                        yield this.refreshAccessTokenAsync();
+                        return this.requestAsync(opts, true);
+                    }
+                }
+                throw e;
+            }
+            return r2;
+        });
+    }
+    verifyIdToken(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(options).then(r => callback(null, r), callback);
+        }
+        else {
+            return this.verifyIdTokenAsync(options);
+        }
+    }
+    verifyIdTokenAsync(options) {
+        return __awaiter(this, void 0, void 0, function* () {
+            if (!options.idToken) {
+                throw new Error('The verifyIdToken method requires an ID Token');
+            }
+            const response = yield this.getFederatedSignonCertsAsync();
+            const login = yield this.verifySignedJwtWithCertsAsync(options.idToken, response.certs, options.audience, OAuth2Client.ISSUERS_, options.maxExpiry);
+            return login;
+        });
+    }
+    /**
+     * Obtains information about the provisioned access token.  Especially useful
+     * if you want to check the scopes that were provisioned to a given token.
+     *
+     * @param accessToken Required.  The Access Token for which you want to get
+     * user info.
+     */
+    getTokenInfo(accessToken) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const { data } = yield this.transporter.request({
+                method: 'GET',
+                url: OAuth2Client.GOOGLE_TOKEN_INFO_URL,
+                params: { access_token: accessToken }
+            });
+            const info = Object.assign({
+                expiry_date: ((new Date()).getTime() + (data.expires_in * 1000)),
+                scopes: data.scope.split(' ')
+            }, data);
+            delete info.expires_in;
+            delete info.scope;
+            return info;
+        });
+    }
+    getFederatedSignonCerts(callback) {
+        if (callback) {
+            this.getFederatedSignonCertsAsync().then(r => callback(null, r.certs, r.res), callback);
+        }
+        else {
+            return this.getFederatedSignonCertsAsync();
+        }
+    }
+    getFederatedSignonCertsAsync() {
+        return __awaiter(this, void 0, void 0, function* () {
+            const nowTime = (new Date()).getTime();
+            const format = isbrowser_1.isBrowser() ? CertificateFormat.JWK : CertificateFormat.PEM;
+            if (this.certificateExpiry &&
+                (nowTime < this.certificateExpiry.getTime()) &&
+                this.certificateCacheFormat === format) {
+                return { certs: this.certificateCache, format };
+            }
+            let res;
+            let url;
+            switch (format) {
+                case CertificateFormat.PEM:
+                    url = OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_PEM_CERTS_URL_;
+                    break;
+                case CertificateFormat.JWK:
+                    url = OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_JWK_CERTS_URL_;
+                    break;
+                default:
+                    throw new Error(`Unsupported certificate format ${format}`);
+            }
+            try {
+                res = yield this.transporter.request({ url });
+            }
+            catch (e) {
+                throw new Error('Failed to retrieve verification certificates: ' + e);
+            }
+            const cacheControl = res ? res.headers['cache-control'] : undefined;
+            let cacheAge = -1;
+            if (cacheControl) {
+                const pattern = new RegExp('max-age=([0-9]*)');
+                const regexResult = pattern.exec(cacheControl);
+                if (regexResult && regexResult.length === 2) {
+                    // Cache results with max-age (in seconds)
+                    cacheAge = Number(regexResult[1]) * 1000; // milliseconds
+                }
+            }
+            let certificates = {};
+            switch (format) {
+                case CertificateFormat.PEM:
+                    certificates = res.data;
+                    break;
+                case CertificateFormat.JWK:
+                    for (const key of res.data.keys) {
+                        certificates[key.kid] = key;
+                    }
+                    break;
+                default:
+                    throw new Error(`Unsupported certificate format ${format}`);
+            }
+            const now = new Date();
+            this.certificateExpiry =
+                cacheAge === -1 ? null : new Date(now.getTime() + cacheAge);
+            this.certificateCache = certificates;
+            this.certificateCacheFormat = format;
+            return { certs: certificates, format, res };
+        });
+    }
+    verifySignedJwtWithCerts() {
+        // To make the code compatible with browser SubtleCrypto we need to make
+        // this method async.
+        throw new Error('verifySignedJwtWithCerts is removed, please use verifySignedJwtWithCertsAsync instead.');
+    }
+    /**
+     * Verify the id token is signed with the correct certificate
+     * and is from the correct audience.
+     * @param jwt The jwt to verify (The ID Token in this case).
+     * @param certs The array of certs to test the jwt against.
+     * @param requiredAudience The audience to test the jwt against.
+     * @param issuers The allowed issuers of the jwt (Optional).
+     * @param maxExpiry The max expiry the certificate can be (Optional).
+     * @return Returns a promise resolving to LoginTicket on verification.
+     */
+    verifySignedJwtWithCertsAsync(jwt, certs, requiredAudience, issuers, maxExpiry) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const crypto = crypto_1.createCrypto();
+            if (!maxExpiry) {
+                maxExpiry = OAuth2Client.MAX_TOKEN_LIFETIME_SECS_;
+            }
+            const segments = jwt.split('.');
+            if (segments.length !== 3) {
+                throw new Error('Wrong number of segments in token: ' + jwt);
+            }
+            const signed = segments[0] + '.' + segments[1];
+            const signature = segments[2];
+            let envelope;
+            let payload;
+            try {
+                envelope = JSON.parse(crypto.decodeBase64StringUtf8(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(crypto.decodeBase64StringUtf8(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));
+            }
+            const cert = certs[envelope.kid];
+            const verified = yield crypto.verify(cert, signed, signature);
+            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));
+            }
+            const iat = Number(payload.iat);
+            if (isNaN(iat))
+                throw new Error('iat field using invalid format');
+            const exp = Number(payload.exp);
+            if (isNaN(exp))
+                throw new Error('exp field using invalid format');
+            const now = new Date().getTime() / 1000;
+            if (exp >= now + maxExpiry) {
+                throw new Error('Expiration time too far in future: ' + JSON.stringify(payload));
+            }
+            const earliest = iat - OAuth2Client.CLOCK_SKEW_SECS_;
+            const 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) {
+                const aud = payload.aud;
+                let 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);
+        });
+    }
+    /**
+     * Returns true if a token is expired or will expire within
+     * eagerRefreshThresholdMillismilliseconds.
+     * If there is no expiry time, assumes the token is not expired or expiring.
+     */
+    isTokenExpiring() {
+        const expiryDate = this.credentials.expiry_date;
+        return expiryDate ? expiryDate <=
+            ((new Date()).getTime() + this.eagerRefreshThresholdMillis) :
+            false;
+    }
+}
+OAuth2Client.GOOGLE_TOKEN_INFO_URL = 'https://oauth2.googleapis.com/tokeninfo';
+/**
+ * The base URL for auth endpoints.
+ */
+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://oauth2.googleapis.com/token';
+/**
+ * The base endpoint to revoke tokens.
+ */
+OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_ = 'https://oauth2.googleapis.com/revoke';
+/**
+ * Google Sign on certificates in PEM format.
+ */
+OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_PEM_CERTS_URL_ = 'https://www.googleapis.com/oauth2/v1/certs';
+/**
+ * Google Sign on certificates in JWK format.
+ */
+OAuth2Client.GOOGLE_OAUTH2_FEDERATED_SIGNON_JWK_CERTS_URL_ = 'https://www.googleapis.com/oauth2/v3/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
\ No newline at end of file