mirror of
https://github.com/titanscouting/tra-analysis.git
synced 2025-09-23 05:40:19 +00:00
push all website files
This commit is contained in:
279
website/functions/node_modules/firebase-admin/lib/auth/token-verifier.js
generated
vendored
Normal file
279
website/functions/node_modules/firebase-admin/lib/auth/token-verifier.js
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
/*! firebase-admin v6.0.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var error_1 = require("../utils/error");
|
||||
var validator = require("../utils/validator");
|
||||
var jwt = require("jsonwebtoken");
|
||||
// Audience to use for Firebase Auth Custom tokens
|
||||
var FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
|
||||
exports.ALGORITHM_RS256 = 'RS256';
|
||||
// URL containing the public keys for the Google certs (whose private keys are used to sign Firebase
|
||||
// Auth ID tokens)
|
||||
var CLIENT_CERT_URL = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';
|
||||
// URL containing the public keys for Firebase session cookies. This will be updated to a different URL soon.
|
||||
var SESSION_COOKIE_CERT_URL = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys';
|
||||
/** User facing token information related to the Firebase ID token. */
|
||||
exports.ID_TOKEN_INFO = {
|
||||
url: 'https://firebase.google.com/docs/auth/admin/verify-id-tokens',
|
||||
verifyApiName: 'verifyIdToken()',
|
||||
jwtName: 'Firebase ID token',
|
||||
shortName: 'ID token',
|
||||
expiredErrorCode: 'auth/id-token-expired',
|
||||
};
|
||||
/** User facing token information related to the Firebase session cookie. */
|
||||
exports.SESSION_COOKIE_INFO = {
|
||||
url: 'https://firebase.google.com/docs/auth/admin/manage-cookies',
|
||||
verifyApiName: 'verifySessionCookie()',
|
||||
jwtName: 'Firebase session cookie',
|
||||
shortName: 'session cookie',
|
||||
expiredErrorCode: 'auth/session-cookie-expired',
|
||||
};
|
||||
/**
|
||||
* Class for verifying general purpose Firebase JWTs. This verifies ID tokens and session cookies.
|
||||
*/
|
||||
var FirebaseTokenVerifier = /** @class */ (function () {
|
||||
function FirebaseTokenVerifier(clientCertUrl, algorithm, issuer, projectId, tokenInfo) {
|
||||
this.clientCertUrl = clientCertUrl;
|
||||
this.algorithm = algorithm;
|
||||
this.issuer = issuer;
|
||||
this.projectId = projectId;
|
||||
this.tokenInfo = tokenInfo;
|
||||
if (!validator.isURL(clientCertUrl)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided public client certificate URL is an invalid URL.");
|
||||
}
|
||||
else if (!validator.isNonEmptyString(algorithm)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT algorithm is an empty string.");
|
||||
}
|
||||
else if (!validator.isURL(issuer)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT issuer is an invalid URL.");
|
||||
}
|
||||
else if (!validator.isNonNullObject(tokenInfo)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT information is not an object or null.");
|
||||
}
|
||||
else if (!validator.isURL(tokenInfo.url)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT verification documentation URL is invalid.");
|
||||
}
|
||||
else if (!validator.isNonEmptyString(tokenInfo.verifyApiName)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT verify API name must be a non-empty string.");
|
||||
}
|
||||
else if (!validator.isNonEmptyString(tokenInfo.jwtName)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT public full name must be a non-empty string.");
|
||||
}
|
||||
else if (!validator.isNonEmptyString(tokenInfo.shortName)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT public short name must be a non-empty string.");
|
||||
}
|
||||
else if (!validator.isNonEmptyString(tokenInfo.expiredErrorCode)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT expiration error code must be a non-empty string.");
|
||||
}
|
||||
this.shortNameArticle = tokenInfo.shortName.charAt(0).match(/[aeiou]/i) ? 'an' : 'a';
|
||||
// For backward compatibility, the project ID is validated in the verification call.
|
||||
}
|
||||
/**
|
||||
* Verifies the format and signature of a Firebase Auth JWT token.
|
||||
*
|
||||
* @param {string} jwtToken The Firebase Auth JWT token to verify.
|
||||
* @return {Promise<object>} A promise fulfilled with the decoded claims of the Firebase Auth ID
|
||||
* token.
|
||||
*/
|
||||
FirebaseTokenVerifier.prototype.verifyJWT = function (jwtToken) {
|
||||
var _this = this;
|
||||
if (!validator.isString(jwtToken)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "First argument to " + this.tokenInfo.verifyApiName + " must be a " + this.tokenInfo.jwtName + " string.");
|
||||
}
|
||||
if (!validator.isNonEmptyString(this.projectId)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, "Must initialize app with a cert credential or set your Firebase project ID as the " +
|
||||
("GOOGLE_CLOUD_PROJECT environment variable to call " + this.tokenInfo.verifyApiName + "."));
|
||||
}
|
||||
var fullDecodedToken = jwt.decode(jwtToken, {
|
||||
complete: true,
|
||||
});
|
||||
var header = fullDecodedToken && fullDecodedToken.header;
|
||||
var payload = fullDecodedToken && fullDecodedToken.payload;
|
||||
var projectIdMatchMessage = " Make sure the " + this.tokenInfo.shortName + " comes from the same " +
|
||||
"Firebase project as the service account used to authenticate this SDK.";
|
||||
var verifyJwtTokenDocsMessage = " See " + this.tokenInfo.url + " " +
|
||||
("for details on how to retrieve " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".");
|
||||
var errorMessage;
|
||||
if (!fullDecodedToken) {
|
||||
errorMessage = "Decoding " + this.tokenInfo.jwtName + " failed. Make sure you passed the entire string JWT " +
|
||||
("which represents " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".") + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (typeof header.kid === 'undefined') {
|
||||
var isCustomToken = (payload.aud === FIREBASE_AUDIENCE);
|
||||
var isLegacyCustomToken = (header.alg === 'HS256' && payload.v === 0 && 'd' in payload && 'uid' in payload.d);
|
||||
if (isCustomToken) {
|
||||
errorMessage = this.tokenInfo.verifyApiName + " expects " + this.shortNameArticle + " " +
|
||||
(this.tokenInfo.shortName + ", but was given a custom token.");
|
||||
}
|
||||
else if (isLegacyCustomToken) {
|
||||
errorMessage = this.tokenInfo.verifyApiName + " expects " + this.shortNameArticle + " " +
|
||||
(this.tokenInfo.shortName + ", but was given a legacy custom token.");
|
||||
}
|
||||
else {
|
||||
errorMessage = 'Firebase ID token has no "kid" claim.';
|
||||
}
|
||||
errorMessage += verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (header.alg !== this.algorithm) {
|
||||
errorMessage = this.tokenInfo.jwtName + " has incorrect algorithm. Expected \"" + this.algorithm + "\" but got " +
|
||||
"\"" + header.alg + "\"." + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (payload.aud !== this.projectId) {
|
||||
errorMessage = this.tokenInfo.jwtName + " has incorrect \"aud\" (audience) claim. Expected \"" +
|
||||
this.projectId + "\" but got \"" + payload.aud + "\"." + projectIdMatchMessage +
|
||||
verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (payload.iss !== this.issuer + this.projectId) {
|
||||
errorMessage = this.tokenInfo.jwtName + " has incorrect \"iss\" (issuer) claim. Expected " +
|
||||
("\"" + this.issuer + "\"") + this.projectId + "\" but got \"" +
|
||||
payload.iss + "\"." + projectIdMatchMessage + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (typeof payload.sub !== 'string') {
|
||||
errorMessage = this.tokenInfo.jwtName + " has no \"sub\" (subject) claim." + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (payload.sub === '') {
|
||||
errorMessage = this.tokenInfo.jwtName + " has an empty string \"sub\" (subject) claim." + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (payload.sub.length > 128) {
|
||||
errorMessage = this.tokenInfo.jwtName + " has \"sub\" (subject) claim longer than 128 characters." +
|
||||
verifyJwtTokenDocsMessage;
|
||||
}
|
||||
if (typeof errorMessage !== 'undefined') {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage));
|
||||
}
|
||||
return this.fetchPublicKeys().then(function (publicKeys) {
|
||||
if (!publicKeys.hasOwnProperty(header.kid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, _this.tokenInfo.jwtName + " has \"kid\" claim which does not correspond to a known public key. " +
|
||||
("Most likely the " + _this.tokenInfo.shortName + " is expired, so get a fresh token from your ") +
|
||||
"client app and try again."));
|
||||
}
|
||||
else {
|
||||
return _this.verifyJwtSignatureWithKey(jwtToken, publicKeys[header.kid]);
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Verifies the JWT signature using the provided public key.
|
||||
* @param {string} jwtToken The JWT token to verify.
|
||||
* @param {string} publicKey The public key certificate.
|
||||
* @return {Promise<object>} A promise that resolves with the decoded JWT claims on successful
|
||||
* verification.
|
||||
*/
|
||||
FirebaseTokenVerifier.prototype.verifyJwtSignatureWithKey = function (jwtToken, publicKey) {
|
||||
var _this = this;
|
||||
var errorMessage;
|
||||
var verifyJwtTokenDocsMessage = " See " + this.tokenInfo.url + " " +
|
||||
("for details on how to retrieve " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".");
|
||||
return new Promise(function (resolve, reject) {
|
||||
jwt.verify(jwtToken, publicKey, {
|
||||
algorithms: [_this.algorithm],
|
||||
}, function (error, decodedToken) {
|
||||
if (error) {
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
errorMessage = _this.tokenInfo.jwtName + " has expired. Get a fresh token from your client " +
|
||||
("app and try again (" + _this.tokenInfo.expiredErrorCode + ").") + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
else if (error.name === 'JsonWebTokenError') {
|
||||
errorMessage = _this.tokenInfo.jwtName + " has invalid signature." + verifyJwtTokenDocsMessage;
|
||||
}
|
||||
return reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage));
|
||||
}
|
||||
else {
|
||||
decodedToken.uid = decodedToken.sub;
|
||||
resolve(decodedToken);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Fetches the public keys for the Google certs.
|
||||
*
|
||||
* @return {Promise<object>} A promise fulfilled with public keys for the Google certs.
|
||||
*/
|
||||
FirebaseTokenVerifier.prototype.fetchPublicKeys = function () {
|
||||
var _this = this;
|
||||
var publicKeysExist = (typeof this.publicKeys !== 'undefined');
|
||||
var publicKeysExpiredExists = (typeof this.publicKeysExpireAt !== 'undefined');
|
||||
var publicKeysStillValid = (publicKeysExpiredExists && Date.now() < this.publicKeysExpireAt);
|
||||
if (publicKeysExist && publicKeysStillValid) {
|
||||
return Promise.resolve(this.publicKeys);
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
var https = require('https');
|
||||
https.get(_this.clientCertUrl, function (res) {
|
||||
var buffers = [];
|
||||
res.on('data', function (buffer) { return buffers.push(buffer); });
|
||||
res.on('end', function () {
|
||||
try {
|
||||
var response = JSON.parse(Buffer.concat(buffers).toString());
|
||||
if (response.error) {
|
||||
var errorMessage = 'Error fetching public keys for Google certs: ' + response.error;
|
||||
/* istanbul ignore else */
|
||||
if (response.error_description) {
|
||||
errorMessage += ' (' + response.error_description + ')';
|
||||
}
|
||||
reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, errorMessage));
|
||||
}
|
||||
else {
|
||||
/* istanbul ignore else */
|
||||
if (res.headers.hasOwnProperty('cache-control')) {
|
||||
var cacheControlHeader = res.headers['cache-control'];
|
||||
var parts = cacheControlHeader.split(',');
|
||||
parts.forEach(function (part) {
|
||||
var subParts = part.trim().split('=');
|
||||
if (subParts[0] === 'max-age') {
|
||||
var maxAge = +subParts[1];
|
||||
_this.publicKeysExpireAt = Date.now() + (maxAge * 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
_this.publicKeys = response;
|
||||
resolve(response);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
/* istanbul ignore next */
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}).on('error', reject);
|
||||
});
|
||||
};
|
||||
return FirebaseTokenVerifier;
|
||||
}());
|
||||
exports.FirebaseTokenVerifier = FirebaseTokenVerifier;
|
||||
/**
|
||||
* Creates a new FirebaseTokenVerifier to verify Firebase ID tokens.
|
||||
*
|
||||
* @param {string} projectId Project ID string.
|
||||
* @return {FirebaseTokenVerifier}
|
||||
*/
|
||||
function createIdTokenVerifier(projectId) {
|
||||
return new FirebaseTokenVerifier(CLIENT_CERT_URL, exports.ALGORITHM_RS256, 'https://securetoken.google.com/', projectId, exports.ID_TOKEN_INFO);
|
||||
}
|
||||
exports.createIdTokenVerifier = createIdTokenVerifier;
|
||||
/**
|
||||
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
|
||||
*
|
||||
* @param {string} projectId Project ID string.
|
||||
* @return {FirebaseTokenVerifier}
|
||||
*/
|
||||
function createSessionCookieVerifier(projectId) {
|
||||
return new FirebaseTokenVerifier(SESSION_COOKIE_CERT_URL, exports.ALGORITHM_RS256, 'https://session.firebase.google.com/', projectId, exports.SESSION_COOKIE_INFO);
|
||||
}
|
||||
exports.createSessionCookieVerifier = createSessionCookieVerifier;
|
Reference in New Issue
Block a user