Firebase Update
This commit is contained in:
117
express-server/node_modules/firebase-admin/lib/auth/action-code-settings-builder.js
generated
vendored
Normal file
117
express-server/node_modules/firebase-admin/lib/auth/action-code-settings-builder.js
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*! firebase-admin v6.4.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 validator = require("../utils/validator");
|
||||
var error_1 = require("../utils/error");
|
||||
/**
|
||||
* Defines the ActionCodeSettings builder class used to convert the
|
||||
* ActionCodeSettings object to its corresponding server request.
|
||||
*/
|
||||
var ActionCodeSettingsBuilder = /** @class */ (function () {
|
||||
/**
|
||||
* ActionCodeSettingsBuilder constructor.
|
||||
*
|
||||
* @param {ActionCodeSettings} actionCodeSettings The ActionCodeSettings
|
||||
* object used to initiliaze this server request builder.
|
||||
* @constructor
|
||||
*/
|
||||
function ActionCodeSettingsBuilder(actionCodeSettings) {
|
||||
if (!validator.isNonNullObject(actionCodeSettings)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings" must be a non-null object.');
|
||||
}
|
||||
if (typeof actionCodeSettings.url === 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_CONTINUE_URI);
|
||||
}
|
||||
else if (!validator.isURL(actionCodeSettings.url)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONTINUE_URI);
|
||||
}
|
||||
this.continueUrl = actionCodeSettings.url;
|
||||
if (typeof actionCodeSettings.handleCodeInApp !== 'undefined' &&
|
||||
!validator.isBoolean(actionCodeSettings.handleCodeInApp)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.handleCodeInApp" must be a boolean.');
|
||||
}
|
||||
this.canHandleCodeInApp = actionCodeSettings.handleCodeInApp || false;
|
||||
if (typeof actionCodeSettings.dynamicLinkDomain !== 'undefined' &&
|
||||
!validator.isNonEmptyString(actionCodeSettings.dynamicLinkDomain)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DYNAMIC_LINK_DOMAIN);
|
||||
}
|
||||
this.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
|
||||
if (typeof actionCodeSettings.iOS !== 'undefined') {
|
||||
if (!validator.isNonNullObject(actionCodeSettings.iOS)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS" must be a valid non-null object.');
|
||||
}
|
||||
else if (typeof actionCodeSettings.iOS.bundleId === 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_IOS_BUNDLE_ID);
|
||||
}
|
||||
else if (!validator.isNonEmptyString(actionCodeSettings.iOS.bundleId)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS.bundleId" must be a valid non-empty string.');
|
||||
}
|
||||
this.ibi = actionCodeSettings.iOS.bundleId;
|
||||
}
|
||||
if (typeof actionCodeSettings.android !== 'undefined') {
|
||||
if (!validator.isNonNullObject(actionCodeSettings.android)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android" must be a valid non-null object.');
|
||||
}
|
||||
else if (typeof actionCodeSettings.android.packageName === 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME);
|
||||
}
|
||||
else if (!validator.isNonEmptyString(actionCodeSettings.android.packageName)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.packageName" must be a valid non-empty string.');
|
||||
}
|
||||
else if (typeof actionCodeSettings.android.minimumVersion !== 'undefined' &&
|
||||
!validator.isNonEmptyString(actionCodeSettings.android.minimumVersion)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.minimumVersion" must be a valid non-empty string.');
|
||||
}
|
||||
else if (typeof actionCodeSettings.android.installApp !== 'undefined' &&
|
||||
!validator.isBoolean(actionCodeSettings.android.installApp)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.installApp" must be a valid boolean.');
|
||||
}
|
||||
this.apn = actionCodeSettings.android.packageName;
|
||||
this.amv = actionCodeSettings.android.minimumVersion;
|
||||
this.installApp = actionCodeSettings.android.installApp || false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the corresponding constructed server request corresponding to the
|
||||
* current ActionCodeSettings.
|
||||
*
|
||||
* @return {EmailActionCodeRequest} The constructed EmailActionCodeRequest request.
|
||||
*/
|
||||
ActionCodeSettingsBuilder.prototype.buildRequest = function () {
|
||||
var request = {
|
||||
continueUrl: this.continueUrl,
|
||||
canHandleCodeInApp: this.canHandleCodeInApp,
|
||||
dynamicLinkDomain: this.dynamicLinkDomain,
|
||||
androidPackageName: this.apn,
|
||||
androidMinimumVersion: this.amv,
|
||||
androidInstallApp: this.installApp,
|
||||
iOSBundleId: this.ibi,
|
||||
};
|
||||
// Remove all null and undefined fields from request.
|
||||
for (var key in request) {
|
||||
if (request.hasOwnProperty(key)) {
|
||||
if (typeof request[key] === 'undefined' || request[key] === null) {
|
||||
delete request[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
};
|
||||
return ActionCodeSettingsBuilder;
|
||||
}());
|
||||
exports.ActionCodeSettingsBuilder = ActionCodeSettingsBuilder;
|
825
express-server/node_modules/firebase-admin/lib/auth/auth-api-request.js
generated
vendored
Normal file
825
express-server/node_modules/firebase-admin/lib/auth/auth-api-request.js
generated
vendored
Normal file
@ -0,0 +1,825 @@
|
||||
/*! firebase-admin v6.4.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2017 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 validator = require("../utils/validator");
|
||||
var deep_copy_1 = require("../utils/deep-copy");
|
||||
var error_1 = require("../utils/error");
|
||||
var api_request_1 = require("../utils/api-request");
|
||||
var user_import_builder_1 = require("./user-import-builder");
|
||||
var utils = require("../utils/index");
|
||||
var action_code_settings_builder_1 = require("./action-code-settings-builder");
|
||||
/** Firebase Auth backend host. */
|
||||
var FIREBASE_AUTH_HOST = 'www.googleapis.com';
|
||||
/** Firebase Auth backend port number. */
|
||||
var FIREBASE_AUTH_PORT = 443;
|
||||
/** Firebase Auth backend path. */
|
||||
var FIREBASE_AUTH_PATH = '/identitytoolkit/v3/relyingparty/';
|
||||
/** Firebase Auth request header. */
|
||||
var FIREBASE_AUTH_HEADER = {
|
||||
'X-Client-Version': 'Node/Admin/6.4.0',
|
||||
};
|
||||
/** Firebase Auth request timeout duration in milliseconds. */
|
||||
var FIREBASE_AUTH_TIMEOUT = 25000;
|
||||
/** List of reserved claims which cannot be provided when creating a custom token. */
|
||||
exports.RESERVED_CLAIMS = [
|
||||
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat',
|
||||
'iss', 'jti', 'nbf', 'nonce', 'sub', 'firebase',
|
||||
];
|
||||
/** List of supported email action request types. */
|
||||
exports.EMAIL_ACTION_REQUEST_TYPES = [
|
||||
'PASSWORD_RESET', 'VERIFY_EMAIL', 'EMAIL_SIGNIN',
|
||||
];
|
||||
/** Maximum allowed number of characters in the custom claims payload. */
|
||||
var MAX_CLAIMS_PAYLOAD_SIZE = 1000;
|
||||
/** Maximum allowed number of users to batch download at one time. */
|
||||
var MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE = 1000;
|
||||
/** Maximum allowed number of users to batch upload at one time. */
|
||||
var MAX_UPLOAD_ACCOUNT_BATCH_SIZE = 1000;
|
||||
/** Minimum allowed session cookie duration in seconds (5 minutes). */
|
||||
var MIN_SESSION_COOKIE_DURATION_SECS = 5 * 60;
|
||||
/** Maximum allowed session cookie duration in seconds (2 weeks). */
|
||||
var MAX_SESSION_COOKIE_DURATION_SECS = 14 * 24 * 60 * 60;
|
||||
/** The Firebase Auth backend URL format. */
|
||||
var FIREBASE_AUTH_BASE_URL_FORMAT = 'https://identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
|
||||
/** Defines a base utility to help with resource URL construction. */
|
||||
var AuthResourceUrlBuilder = /** @class */ (function () {
|
||||
/**
|
||||
* The resource URL builder constructor.
|
||||
*
|
||||
* @param {string} projectId The resource project ID.
|
||||
* @param {string} version The endpoint API version.
|
||||
* @constructor
|
||||
*/
|
||||
function AuthResourceUrlBuilder(projectId, version) {
|
||||
if (version === void 0) { version = 'v1'; }
|
||||
this.projectId = projectId;
|
||||
this.version = version;
|
||||
this.urlFormat = FIREBASE_AUTH_BASE_URL_FORMAT;
|
||||
}
|
||||
/**
|
||||
* Returns the resource URL corresponding to the provided parameters.
|
||||
*
|
||||
* @param {string=} api The backend API name.
|
||||
* @param {object=} params The optional additional parameters to substitute in the
|
||||
* URL path.
|
||||
* @return {string} The corresponding resource URL.
|
||||
*/
|
||||
AuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
|
||||
var baseParams = {
|
||||
version: this.version,
|
||||
projectId: this.projectId,
|
||||
api: api || '',
|
||||
};
|
||||
var baseUrl = utils.formatString(this.urlFormat, baseParams);
|
||||
// Substitute additional api related parameters.
|
||||
return utils.formatString(baseUrl, params || {});
|
||||
};
|
||||
return AuthResourceUrlBuilder;
|
||||
}());
|
||||
/**
|
||||
* Validates a providerUserInfo object. All unsupported parameters
|
||||
* are removed from the original request. If an invalid field is passed
|
||||
* an error is thrown.
|
||||
*
|
||||
* @param {any} request The providerUserInfo request object.
|
||||
*/
|
||||
function validateProviderUserInfo(request) {
|
||||
var validKeys = {
|
||||
rawId: true,
|
||||
providerId: true,
|
||||
email: true,
|
||||
displayName: true,
|
||||
photoUrl: true,
|
||||
};
|
||||
// Remove invalid keys from original request.
|
||||
for (var key in request) {
|
||||
if (!(key in validKeys)) {
|
||||
delete request[key];
|
||||
}
|
||||
}
|
||||
if (!validator.isNonEmptyString(request.providerId)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
|
||||
}
|
||||
if (typeof request.displayName !== 'undefined' &&
|
||||
typeof request.displayName !== 'string') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME, "The provider \"displayName\" for \"" + request.providerId + "\" must be a valid string.");
|
||||
}
|
||||
if (!validator.isNonEmptyString(request.rawId)) {
|
||||
// This is called localId on the backend but the developer specifies this as
|
||||
// uid externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, "The provider \"uid\" for \"" + request.providerId + "\" must be a valid non-empty string.");
|
||||
}
|
||||
// email should be a string and a valid email.
|
||||
if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL, "The provider \"email\" for \"" + request.providerId + "\" must be a valid email string.");
|
||||
}
|
||||
// photoUrl should be a URL.
|
||||
if (typeof request.photoUrl !== 'undefined' &&
|
||||
!validator.isURL(request.photoUrl)) {
|
||||
// This is called photoUrl on the backend but the developer specifies this as
|
||||
// photoURL externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL, "The provider \"photoURL\" for \"" + request.providerId + "\" must be a valid URL string.");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates a create/edit request object. All unsupported parameters
|
||||
* are removed from the original request. If an invalid field is passed
|
||||
* an error is thrown.
|
||||
*
|
||||
* @param {any} request The create/edit request object.
|
||||
* @param {boolean=} uploadAccountRequest Whether to validate as an uploadAccount request.
|
||||
*/
|
||||
function validateCreateEditRequest(request, uploadAccountRequest) {
|
||||
if (uploadAccountRequest === void 0) { uploadAccountRequest = false; }
|
||||
// Hash set of whitelisted parameters.
|
||||
var validKeys = {
|
||||
displayName: true,
|
||||
localId: true,
|
||||
email: true,
|
||||
password: true,
|
||||
rawPassword: true,
|
||||
emailVerified: true,
|
||||
photoUrl: true,
|
||||
disabled: true,
|
||||
disableUser: true,
|
||||
deleteAttribute: true,
|
||||
deleteProvider: true,
|
||||
sanityCheck: true,
|
||||
phoneNumber: true,
|
||||
customAttributes: true,
|
||||
validSince: true,
|
||||
passwordHash: uploadAccountRequest,
|
||||
salt: uploadAccountRequest,
|
||||
createdAt: uploadAccountRequest,
|
||||
lastLoginAt: uploadAccountRequest,
|
||||
providerUserInfo: uploadAccountRequest,
|
||||
};
|
||||
// Remove invalid keys from original request.
|
||||
for (var key in request) {
|
||||
if (!(key in validKeys)) {
|
||||
delete request[key];
|
||||
}
|
||||
}
|
||||
// For any invalid parameter, use the external key name in the error description.
|
||||
// displayName should be a string.
|
||||
if (typeof request.displayName !== 'undefined' &&
|
||||
!validator.isString(request.displayName)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME);
|
||||
}
|
||||
if ((typeof request.localId !== 'undefined' || uploadAccountRequest) &&
|
||||
!validator.isUid(request.localId)) {
|
||||
// This is called localId on the backend but the developer specifies this as
|
||||
// uid externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
|
||||
}
|
||||
// email should be a string and a valid email.
|
||||
if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
|
||||
}
|
||||
// phoneNumber should be a string and a valid phone number.
|
||||
if (typeof request.phoneNumber !== 'undefined' &&
|
||||
!validator.isPhoneNumber(request.phoneNumber)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER);
|
||||
}
|
||||
// password should be a string and a minimum of 6 chars.
|
||||
if (typeof request.password !== 'undefined' &&
|
||||
!validator.isPassword(request.password)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
|
||||
}
|
||||
// rawPassword should be a string and a minimum of 6 chars.
|
||||
if (typeof request.rawPassword !== 'undefined' &&
|
||||
!validator.isPassword(request.rawPassword)) {
|
||||
// This is called rawPassword on the backend but the developer specifies this as
|
||||
// password externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
|
||||
}
|
||||
// emailVerified should be a boolean.
|
||||
if (typeof request.emailVerified !== 'undefined' &&
|
||||
typeof request.emailVerified !== 'boolean') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL_VERIFIED);
|
||||
}
|
||||
// photoUrl should be a URL.
|
||||
if (typeof request.photoUrl !== 'undefined' &&
|
||||
!validator.isURL(request.photoUrl)) {
|
||||
// This is called photoUrl on the backend but the developer specifies this as
|
||||
// photoURL externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL);
|
||||
}
|
||||
// disabled should be a boolean.
|
||||
if (typeof request.disabled !== 'undefined' &&
|
||||
typeof request.disabled !== 'boolean') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
|
||||
}
|
||||
// validSince should be a number.
|
||||
if (typeof request.validSince !== 'undefined' &&
|
||||
!validator.isNumber(request.validSince)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TOKENS_VALID_AFTER_TIME);
|
||||
}
|
||||
// createdAt should be a number.
|
||||
if (typeof request.createdAt !== 'undefined' &&
|
||||
!validator.isNumber(request.createdAt)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREATION_TIME);
|
||||
}
|
||||
// lastSignInAt should be a number.
|
||||
if (typeof request.lastLoginAt !== 'undefined' &&
|
||||
!validator.isNumber(request.lastLoginAt)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_LAST_SIGN_IN_TIME);
|
||||
}
|
||||
// disableUser should be a boolean.
|
||||
if (typeof request.disableUser !== 'undefined' &&
|
||||
typeof request.disableUser !== 'boolean') {
|
||||
// This is called disableUser on the backend but the developer specifies this as
|
||||
// disabled externally. So the error message should use the client facing name.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
|
||||
}
|
||||
// customAttributes should be stringified JSON with no blacklisted claims.
|
||||
// The payload should not exceed 1KB.
|
||||
if (typeof request.customAttributes !== 'undefined') {
|
||||
var developerClaims_1;
|
||||
try {
|
||||
developerClaims_1 = JSON.parse(request.customAttributes);
|
||||
}
|
||||
catch (error) {
|
||||
// JSON parsing error. This should never happen as we stringify the claims internally.
|
||||
// However, we still need to check since setAccountInfo via edit requests could pass
|
||||
// this field.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CLAIMS, error.message);
|
||||
}
|
||||
var invalidClaims_1 = [];
|
||||
// Check for any invalid claims.
|
||||
exports.RESERVED_CLAIMS.forEach(function (blacklistedClaim) {
|
||||
if (developerClaims_1.hasOwnProperty(blacklistedClaim)) {
|
||||
invalidClaims_1.push(blacklistedClaim);
|
||||
}
|
||||
});
|
||||
// Throw an error if an invalid claim is detected.
|
||||
if (invalidClaims_1.length > 0) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.FORBIDDEN_CLAIM, invalidClaims_1.length > 1 ?
|
||||
"Developer claims \"" + invalidClaims_1.join('", "') + "\" are reserved and cannot be specified." :
|
||||
"Developer claim \"" + invalidClaims_1[0] + "\" is reserved and cannot be specified.");
|
||||
}
|
||||
// Check claims payload does not exceed maxmimum size.
|
||||
if (request.customAttributes.length > MAX_CLAIMS_PAYLOAD_SIZE) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.CLAIMS_TOO_LARGE, "Developer claims payload should not exceed " + MAX_CLAIMS_PAYLOAD_SIZE + " characters.");
|
||||
}
|
||||
}
|
||||
// passwordHash has to be a base64 encoded string.
|
||||
if (typeof request.passwordHash !== 'undefined' &&
|
||||
!validator.isString(request.passwordHash)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
|
||||
}
|
||||
// salt has to be a base64 encoded string.
|
||||
if (typeof request.salt !== 'undefined' &&
|
||||
!validator.isString(request.salt)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
|
||||
}
|
||||
// providerUserInfo has to be an array of valid UserInfo requests.
|
||||
if (typeof request.providerUserInfo !== 'undefined' &&
|
||||
!validator.isArray(request.providerUserInfo)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_DATA);
|
||||
}
|
||||
else if (validator.isArray(request.providerUserInfo)) {
|
||||
request.providerUserInfo.forEach(function (providerUserInfoEntry) {
|
||||
validateProviderUserInfo(providerUserInfoEntry);
|
||||
});
|
||||
}
|
||||
}
|
||||
/** Instantiates the createSessionCookie endpoint settings. */
|
||||
exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE = new api_request_1.ApiSettings(':createSessionCookie', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
// Validate the ID token is a non-empty string.
|
||||
if (!validator.isNonEmptyString(request.idToken)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ID_TOKEN);
|
||||
}
|
||||
// Validate the custom session cookie duration.
|
||||
if (!validator.isNumber(request.validDuration) ||
|
||||
request.validDuration < MIN_SESSION_COOKIE_DURATION_SECS ||
|
||||
request.validDuration > MAX_SESSION_COOKIE_DURATION_SECS) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
|
||||
}
|
||||
})
|
||||
// Set response validator.
|
||||
.setResponseValidator(function (response) {
|
||||
// Response should always contain the session cookie.
|
||||
if (!validator.isNonEmptyString(response.sessionCookie)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR);
|
||||
}
|
||||
});
|
||||
/** Instantiates the uploadAccount endpoint settings. */
|
||||
exports.FIREBASE_AUTH_UPLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchCreate', 'POST');
|
||||
/** Instantiates the downloadAccount endpoint settings. */
|
||||
exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchGet', 'GET')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
// Validate next page token.
|
||||
if (typeof request.nextPageToken !== 'undefined' &&
|
||||
!validator.isNonEmptyString(request.nextPageToken)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
||||
}
|
||||
// Validate max results.
|
||||
if (!validator.isNumber(request.maxResults) ||
|
||||
request.maxResults <= 0 ||
|
||||
request.maxResults > MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive non-zero number that does not exceed " +
|
||||
("the allowed " + MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE + "."));
|
||||
}
|
||||
});
|
||||
/** Instantiates the getAccountInfo endpoint settings. */
|
||||
exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
if (!request.localId && !request.email && !request.phoneNumber) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
||||
}
|
||||
})
|
||||
// Set response validator.
|
||||
.setResponseValidator(function (response) {
|
||||
if (!response.users) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
|
||||
}
|
||||
});
|
||||
/** Instantiates the deleteAccount endpoint settings. */
|
||||
exports.FIREBASE_AUTH_DELETE_ACCOUNT = new api_request_1.ApiSettings('/accounts:delete', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
if (!request.localId) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
||||
}
|
||||
});
|
||||
/** Instantiates the setAccountInfo endpoint settings for updating existing accounts. */
|
||||
exports.FIREBASE_AUTH_SET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:update', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
// localId is a required parameter.
|
||||
if (typeof request.localId === 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
||||
}
|
||||
validateCreateEditRequest(request);
|
||||
})
|
||||
// Set response validator.
|
||||
.setResponseValidator(function (response) {
|
||||
// If the localId is not returned, then the request failed.
|
||||
if (!response.localId) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Instantiates the signupNewUser endpoint settings for creating a new user with or without
|
||||
* uid being specified. The backend will create a new one if not provided and return it.
|
||||
*/
|
||||
exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = new api_request_1.ApiSettings('/accounts', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
// signupNewUser does not support customAttributes.
|
||||
if (typeof request.customAttributes !== 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"customAttributes\" cannot be set when creating a new user.");
|
||||
}
|
||||
// signupNewUser does not support validSince.
|
||||
if (typeof request.validSince !== 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"validSince\" cannot be set when creating a new user.");
|
||||
}
|
||||
validateCreateEditRequest(request);
|
||||
})
|
||||
// Set response validator.
|
||||
.setResponseValidator(function (response) {
|
||||
// If the localId is not returned, then the request failed.
|
||||
if (!response.localId) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new user');
|
||||
}
|
||||
});
|
||||
var FIREBASE_AUTH_GET_OOB_CODE = new api_request_1.ApiSettings('/accounts:sendOobCode', 'POST')
|
||||
// Set request validator.
|
||||
.setRequestValidator(function (request) {
|
||||
if (!validator.isEmail(request.email)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
|
||||
}
|
||||
if (exports.EMAIL_ACTION_REQUEST_TYPES.indexOf(request.requestType) === -1) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"" + request.requestType + "\" is not a supported email action request type.");
|
||||
}
|
||||
})
|
||||
// Set response validator.
|
||||
.setResponseValidator(function (response) {
|
||||
// If the oobLink is not returned, then the request failed.
|
||||
if (!response.oobLink) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create the email action link');
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Class that provides the mechanism to send requests to the Firebase Auth backend endpoints.
|
||||
*/
|
||||
var FirebaseAuthRequestHandler = /** @class */ (function () {
|
||||
/**
|
||||
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
||||
* @constructor
|
||||
*/
|
||||
function FirebaseAuthRequestHandler(app) {
|
||||
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
|
||||
this.authUrlBuilder = new AuthResourceUrlBuilder(utils.getProjectId(app), 'v1');
|
||||
}
|
||||
/**
|
||||
* @param {any} response The response to check for errors.
|
||||
* @return {string|null} The error code if present; null otherwise.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.getErrorCode = function (response) {
|
||||
return (validator.isNonNullObject(response) && response.error && response.error.message) || null;
|
||||
};
|
||||
/**
|
||||
* Creates a new Firebase session cookie with the specified duration that can be used for
|
||||
* session management (set as a server side session cookie with custom cookie policy).
|
||||
* The session cookie JWT will have the same payload claims as the provided ID token.
|
||||
*
|
||||
* @param {string} idToken The Firebase ID token to exchange for a session cookie.
|
||||
* @param {number} expiresIn The session cookie duration in milliseconds.
|
||||
*
|
||||
* @return {Promise<string>} A promise that resolves on success with the created session cookie.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.createSessionCookie = function (idToken, expiresIn) {
|
||||
var request = {
|
||||
idToken: idToken,
|
||||
// Convert to seconds.
|
||||
validDuration: expiresIn / 1000,
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE, request)
|
||||
.then(function (response) { return response.sessionCookie; });
|
||||
};
|
||||
/**
|
||||
* Looks up a user by uid.
|
||||
*
|
||||
* @param {string} uid The uid of the user to lookup.
|
||||
* @return {Promise<object>} A promise that resolves with the user information.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.getAccountInfoByUid = function (uid) {
|
||||
if (!validator.isUid(uid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
||||
}
|
||||
var request = {
|
||||
localId: [uid],
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
||||
};
|
||||
/**
|
||||
* Looks up a user by email.
|
||||
*
|
||||
* @param {string} email The email of the user to lookup.
|
||||
* @return {Promise<object>} A promise that resolves with the user information.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.getAccountInfoByEmail = function (email) {
|
||||
if (!validator.isEmail(email)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL));
|
||||
}
|
||||
var request = {
|
||||
email: [email],
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
||||
};
|
||||
/**
|
||||
* Looks up a user by phone number.
|
||||
*
|
||||
* @param {string} phoneNumber The phone number of the user to lookup.
|
||||
* @return {Promise<object>} A promise that resolves with the user information.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.getAccountInfoByPhoneNumber = function (phoneNumber) {
|
||||
if (!validator.isPhoneNumber(phoneNumber)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER));
|
||||
}
|
||||
var request = {
|
||||
phoneNumber: [phoneNumber],
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
||||
};
|
||||
/**
|
||||
* Exports the users (single batch only) with a size of maxResults and starting from
|
||||
* the offset as specified by pageToken.
|
||||
*
|
||||
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
|
||||
* allowed limit.
|
||||
* @param {string=} pageToken The next page token. If not specified, returns users starting
|
||||
* without any offset. Users are returned in the order they were created from oldest to
|
||||
* newest, relative to the page token offset.
|
||||
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
|
||||
* users and the next page token if available. For the last page, an empty list of users
|
||||
* and no page token are returned.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.downloadAccount = function (maxResults, pageToken) {
|
||||
if (maxResults === void 0) { maxResults = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE; }
|
||||
// Construct request.
|
||||
var request = {
|
||||
maxResults: maxResults,
|
||||
nextPageToken: pageToken,
|
||||
};
|
||||
// Remove next page token if not provided.
|
||||
if (typeof request.nextPageToken === 'undefined') {
|
||||
delete request.nextPageToken;
|
||||
}
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT, request)
|
||||
.then(function (response) {
|
||||
// No more users available.
|
||||
if (!response.users) {
|
||||
response.users = [];
|
||||
}
|
||||
return response;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Imports the list of users provided to Firebase Auth. This is useful when
|
||||
* migrating from an external authentication system without having to use the Firebase CLI SDK.
|
||||
* At most, 1000 users are allowed to be imported one at a time.
|
||||
* When importing a list of password users, UserImportOptions are required to be specified.
|
||||
*
|
||||
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
|
||||
* @param {UserImportOptions=} options The user import options, required when the users provided
|
||||
* include password credentials.
|
||||
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
|
||||
* with the result of the import. This includes the number of successful imports, the number
|
||||
* of failed uploads and their corresponding errors.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.uploadAccount = function (users, options) {
|
||||
// This will throw if any error is detected in the hash options.
|
||||
// For errors in the list of users, this will not throw and will report the errors and the
|
||||
// corresponding user index in the user import generated response below.
|
||||
// No need to validate raw request or raw response as this is done in UserImportBuilder.
|
||||
var userImportBuilder = new user_import_builder_1.UserImportBuilder(users, options, function (userRequest) {
|
||||
// Pass true to validate the uploadAccount specific fields.
|
||||
validateCreateEditRequest(userRequest, true);
|
||||
});
|
||||
var request = userImportBuilder.buildRequest();
|
||||
// Fail quickly if more users than allowed are to be imported.
|
||||
if (validator.isArray(users) && users.length > MAX_UPLOAD_ACCOUNT_BATCH_SIZE) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, "A maximum of " + MAX_UPLOAD_ACCOUNT_BATCH_SIZE + " users can be imported at once.");
|
||||
}
|
||||
// If no remaining user in request after client side processing, there is no need
|
||||
// to send the request to the server.
|
||||
if (request.users.length === 0) {
|
||||
return Promise.resolve(userImportBuilder.buildResponse([]));
|
||||
}
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_UPLOAD_ACCOUNT, request)
|
||||
.then(function (response) {
|
||||
// No error object is returned if no error encountered.
|
||||
var failedUploads = (response.error || []);
|
||||
// Rewrite response as UserImportResult and re-insert client previously detected errors.
|
||||
return userImportBuilder.buildResponse(failedUploads);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Deletes an account identified by a uid.
|
||||
*
|
||||
* @param {string} uid The uid of the user to delete.
|
||||
* @return {Promise<object>} A promise that resolves when the user is deleted.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.deleteAccount = function (uid) {
|
||||
if (!validator.isUid(uid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
||||
}
|
||||
var request = {
|
||||
localId: uid,
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_DELETE_ACCOUNT, request);
|
||||
};
|
||||
/**
|
||||
* Sets additional developer claims on an existing user identified by provided UID.
|
||||
*
|
||||
* @param {string} uid The user to edit.
|
||||
* @param {object} customUserClaims The developer claims to set.
|
||||
* @return {Promise<string>} A promise that resolves when the operation completes
|
||||
* with the user id that was edited.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.setCustomUserClaims = function (uid, customUserClaims) {
|
||||
// Validate user UID.
|
||||
if (!validator.isUid(uid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
||||
}
|
||||
else if (!validator.isObject(customUserClaims)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'CustomUserClaims argument must be an object or null.'));
|
||||
}
|
||||
// Delete operation. Replace null with an empty object.
|
||||
if (customUserClaims === null) {
|
||||
customUserClaims = {};
|
||||
}
|
||||
// Construct custom user attribute editting request.
|
||||
var request = {
|
||||
localId: uid,
|
||||
customAttributes: JSON.stringify(customUserClaims),
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
||||
.then(function (response) {
|
||||
return response.localId;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Edits an existing user.
|
||||
*
|
||||
* @param {string} uid The user to edit.
|
||||
* @param {object} properties The properties to set on the user.
|
||||
* @return {Promise<string>} A promise that resolves when the operation completes
|
||||
* with the user id that was edited.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.updateExistingAccount = function (uid, properties) {
|
||||
if (!validator.isUid(uid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
||||
}
|
||||
else if (!validator.isNonNullObject(properties)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
|
||||
}
|
||||
// Build the setAccountInfo request.
|
||||
var request = deep_copy_1.deepCopy(properties);
|
||||
request.localId = uid;
|
||||
// For deleting displayName or photoURL, these values must be passed as null.
|
||||
// They will be removed from the backend request and an additional parameter
|
||||
// deleteAttribute: ['PHOTO_URL', 'DISPLAY_NAME']
|
||||
// with an array of the parameter names to delete will be passed.
|
||||
// Parameters that are deletable and their deleteAttribute names.
|
||||
// Use client facing names, photoURL instead of photoUrl.
|
||||
var deletableParams = {
|
||||
displayName: 'DISPLAY_NAME',
|
||||
photoURL: 'PHOTO_URL',
|
||||
};
|
||||
// Properties to delete if available.
|
||||
request.deleteAttribute = [];
|
||||
for (var key in deletableParams) {
|
||||
if (request[key] === null) {
|
||||
// Add property identifier to list of attributes to delete.
|
||||
request.deleteAttribute.push(deletableParams[key]);
|
||||
// Remove property from request.
|
||||
delete request[key];
|
||||
}
|
||||
}
|
||||
if (request.deleteAttribute.length === 0) {
|
||||
delete request.deleteAttribute;
|
||||
}
|
||||
// For deleting phoneNumber, this value must be passed as null.
|
||||
// It will be removed from the backend request and an additional parameter
|
||||
// deleteProvider: ['phone'] with an array of providerIds (phone in this case),
|
||||
// will be passed.
|
||||
// Currently this applies to phone provider only.
|
||||
if (request.phoneNumber === null) {
|
||||
request.deleteProvider = ['phone'];
|
||||
delete request.phoneNumber;
|
||||
}
|
||||
else {
|
||||
// Doesn't apply to other providers in admin SDK.
|
||||
delete request.deleteProvider;
|
||||
}
|
||||
// Rewrite photoURL to photoUrl.
|
||||
if (typeof request.photoURL !== 'undefined') {
|
||||
request.photoUrl = request.photoURL;
|
||||
delete request.photoURL;
|
||||
}
|
||||
// Rewrite disabled to disableUser.
|
||||
if (typeof request.disabled !== 'undefined') {
|
||||
request.disableUser = request.disabled;
|
||||
delete request.disabled;
|
||||
}
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
||||
.then(function (response) {
|
||||
return response.localId;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Revokes all refresh tokens for the specified user identified by the uid provided.
|
||||
* In addition to revoking all refresh tokens for a user, all ID tokens issued
|
||||
* before revocation will also be revoked on the Auth backend. Any request with an
|
||||
* ID token generated before revocation will be rejected with a token expired error.
|
||||
* Note that due to the fact that the timestamp is stored in seconds, any tokens minted in
|
||||
* the same second as the revocation will still be valid. If there is a chance that a token
|
||||
* was minted in the last second, delay for 1 second before revoking.
|
||||
*
|
||||
* @param {string} uid The user whose tokens are to be revoked.
|
||||
* @return {Promise<string>} A promise that resolves when the operation completes
|
||||
* successfully with the user id of the corresponding user.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.revokeRefreshTokens = function (uid) {
|
||||
// Validate user UID.
|
||||
if (!validator.isUid(uid)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
||||
}
|
||||
var request = {
|
||||
localId: uid,
|
||||
// validSince is in UTC seconds.
|
||||
validSince: Math.ceil(new Date().getTime() / 1000),
|
||||
};
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
||||
.then(function (response) {
|
||||
return response.localId;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Create a new user with the properties supplied.
|
||||
*
|
||||
* @param {object} properties The properties to set on the user.
|
||||
* @return {Promise<string>} A promise that resolves when the operation completes
|
||||
* with the user id that was created.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.createNewAccount = function (properties) {
|
||||
if (!validator.isNonNullObject(properties)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
|
||||
}
|
||||
// Build the signupNewUser request.
|
||||
var request = deep_copy_1.deepCopy(properties);
|
||||
// Rewrite photoURL to photoUrl.
|
||||
if (typeof request.photoURL !== 'undefined') {
|
||||
request.photoUrl = request.photoURL;
|
||||
delete request.photoURL;
|
||||
}
|
||||
// Rewrite uid to localId if it exists.
|
||||
if (typeof request.uid !== 'undefined') {
|
||||
request.localId = request.uid;
|
||||
delete request.uid;
|
||||
}
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SIGN_UP_NEW_USER, request)
|
||||
.then(function (response) {
|
||||
// Return the user id.
|
||||
return response.localId;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Generates the out of band email action link for the email specified using the action code settings provided.
|
||||
* Returns a promise that resolves with the generated link.
|
||||
*
|
||||
* @param {string} requestType The request type. This could be either used for password reset,
|
||||
* email verification, email link sign-in.
|
||||
* @param {string} email The email of the user the link is being sent to.
|
||||
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
|
||||
* the link is to be handled by a mobile app and the additional state information to be passed in the
|
||||
* deep link, etc.
|
||||
* @return {Promise<string>} A promise that resolves with the email action link.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.getEmailActionLink = function (requestType, email, actionCodeSettings) {
|
||||
var request = { requestType: requestType, email: email, returnOobLink: true };
|
||||
// ActionCodeSettings required for email link sign-in to determine the url where the sign-in will
|
||||
// be completed.
|
||||
if (typeof actionCodeSettings !== 'undefined' || requestType === 'EMAIL_SIGNIN') {
|
||||
try {
|
||||
var builder = new action_code_settings_builder_1.ActionCodeSettingsBuilder(actionCodeSettings);
|
||||
request = deep_copy_1.deepExtend(request, builder.buildRequest());
|
||||
}
|
||||
catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
return this.invokeRequestHandler(this.authUrlBuilder, FIREBASE_AUTH_GET_OOB_CODE, request)
|
||||
.then(function (response) {
|
||||
// Return the link.
|
||||
return response.oobLink;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Invokes the request handler based on the API settings object passed.
|
||||
*
|
||||
* @param {AuthResourceUrlBuilder} urlBuilder The URL builder for Auth endpoints.
|
||||
* @param {ApiSettings} apiSettings The API endpoint settings to apply to request and response.
|
||||
* @param {object} requestData The request data.
|
||||
* @param {object=} additionalResourceParams Additional resource related params if needed.
|
||||
* @return {Promise<object>} A promise that resolves with the response.
|
||||
*/
|
||||
FirebaseAuthRequestHandler.prototype.invokeRequestHandler = function (urlBuilder, apiSettings, requestData, additionalResourceParams) {
|
||||
var _this = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
// Validate request.
|
||||
var requestValidator = apiSettings.getRequestValidator();
|
||||
requestValidator(requestData);
|
||||
// Process request.
|
||||
var req = {
|
||||
method: apiSettings.getHttpMethod(),
|
||||
url: urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams),
|
||||
headers: FIREBASE_AUTH_HEADER,
|
||||
data: requestData,
|
||||
timeout: FIREBASE_AUTH_TIMEOUT,
|
||||
};
|
||||
return _this.httpClient.send(req);
|
||||
})
|
||||
.then(function (response) {
|
||||
// Validate response.
|
||||
var responseValidator = apiSettings.getResponseValidator();
|
||||
responseValidator(response.data);
|
||||
// Return entire response.
|
||||
return response.data;
|
||||
})
|
||||
.catch(function (err) {
|
||||
if (err instanceof api_request_1.HttpError) {
|
||||
var error = err.response.data;
|
||||
var errorCode = FirebaseAuthRequestHandler.getErrorCode(error);
|
||||
throw error_1.FirebaseAuthError.fromServerError(errorCode, /* message */ undefined, error);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
return FirebaseAuthRequestHandler;
|
||||
}());
|
||||
exports.FirebaseAuthRequestHandler = FirebaseAuthRequestHandler;
|
437
express-server/node_modules/firebase-admin/lib/auth/auth.js
generated
vendored
Normal file
437
express-server/node_modules/firebase-admin/lib/auth/auth.js
generated
vendored
Normal file
@ -0,0 +1,437 @@
|
||||
/*! firebase-admin v6.4.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var user_record_1 = require("./user-record");
|
||||
var token_generator_1 = require("./token-generator");
|
||||
var auth_api_request_1 = require("./auth-api-request");
|
||||
var error_1 = require("../utils/error");
|
||||
var utils = require("../utils/index");
|
||||
var validator = require("../utils/validator");
|
||||
var token_verifier_1 = require("./token-verifier");
|
||||
/**
|
||||
* Internals of an Auth instance.
|
||||
*/
|
||||
var AuthInternals = /** @class */ (function () {
|
||||
function AuthInternals() {
|
||||
}
|
||||
/**
|
||||
* Deletes the service and its associated resources.
|
||||
*
|
||||
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
|
||||
*/
|
||||
AuthInternals.prototype.delete = function () {
|
||||
// There are no resources to clean up
|
||||
return Promise.resolve(undefined);
|
||||
};
|
||||
return AuthInternals;
|
||||
}());
|
||||
/**
|
||||
* Base Auth class. Mainly used for user management APIs.
|
||||
*/
|
||||
var BaseAuth = /** @class */ (function () {
|
||||
/**
|
||||
* The BaseAuth class constructor.
|
||||
*
|
||||
* @param {string} projectId The corresponding project ID.
|
||||
* @param {FirebaseAuthRequestHandler} authRequestHandler The RPC request handler
|
||||
* for this instance.
|
||||
* @param {CryptoSigner} cryptoSigner The instance crypto signer used for custom token
|
||||
* minting.
|
||||
* @constructor
|
||||
*/
|
||||
function BaseAuth(projectId, authRequestHandler, cryptoSigner) {
|
||||
this.projectId = projectId;
|
||||
this.authRequestHandler = authRequestHandler;
|
||||
this.tokenGenerator = new token_generator_1.FirebaseTokenGenerator(cryptoSigner);
|
||||
this.sessionCookieVerifier = token_verifier_1.createSessionCookieVerifier(projectId);
|
||||
this.idTokenVerifier = token_verifier_1.createIdTokenVerifier(projectId);
|
||||
}
|
||||
/**
|
||||
* Creates a new custom token that can be sent back to a client to use with
|
||||
* signInWithCustomToken().
|
||||
*
|
||||
* @param {string} uid The uid to use as the JWT subject.
|
||||
* @param {object=} developerClaims Optional additional claims to include in the JWT payload.
|
||||
*
|
||||
* @return {Promise<string>} A JWT for the provided payload.
|
||||
*/
|
||||
BaseAuth.prototype.createCustomToken = function (uid, developerClaims) {
|
||||
return this.tokenGenerator.createCustomToken(uid, developerClaims);
|
||||
};
|
||||
/**
|
||||
* Verifies a JWT auth token. Returns a Promise with the tokens claims. Rejects
|
||||
* the promise if the token could not be verified. If checkRevoked is set to true,
|
||||
* verifies if the session corresponding to the ID token was revoked. If the corresponding
|
||||
* user's session was invalidated, an auth/id-token-revoked error is thrown. If not specified
|
||||
* the check is not applied.
|
||||
*
|
||||
* @param {string} idToken The JWT to verify.
|
||||
* @param {boolean=} checkRevoked Whether to check if the ID token is revoked.
|
||||
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
|
||||
* verification.
|
||||
*/
|
||||
BaseAuth.prototype.verifyIdToken = function (idToken, checkRevoked) {
|
||||
var _this = this;
|
||||
if (checkRevoked === void 0) { checkRevoked = false; }
|
||||
return this.idTokenVerifier.verifyJWT(idToken)
|
||||
.then(function (decodedIdToken) {
|
||||
// Whether to check if the token was revoked.
|
||||
if (!checkRevoked) {
|
||||
return decodedIdToken;
|
||||
}
|
||||
return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.ID_TOKEN_REVOKED);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Looks up the user identified by the provided user id and returns a promise that is
|
||||
* fulfilled with a user record for the given user if that user is found.
|
||||
*
|
||||
* @param {string} uid The uid of the user to look up.
|
||||
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
|
||||
*/
|
||||
BaseAuth.prototype.getUser = function (uid) {
|
||||
return this.authRequestHandler.getAccountInfoByUid(uid)
|
||||
.then(function (response) {
|
||||
// Returns the user record populated with server response.
|
||||
return new user_record_1.UserRecord(response.users[0]);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Looks up the user identified by the provided email and returns a promise that is
|
||||
* fulfilled with a user record for the given user if that user is found.
|
||||
*
|
||||
* @param {string} email The email of the user to look up.
|
||||
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
|
||||
*/
|
||||
BaseAuth.prototype.getUserByEmail = function (email) {
|
||||
return this.authRequestHandler.getAccountInfoByEmail(email)
|
||||
.then(function (response) {
|
||||
// Returns the user record populated with server response.
|
||||
return new user_record_1.UserRecord(response.users[0]);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Looks up the user identified by the provided phone number and returns a promise that is
|
||||
* fulfilled with a user record for the given user if that user is found.
|
||||
*
|
||||
* @param {string} phoneNumber The phone number of the user to look up.
|
||||
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
|
||||
*/
|
||||
BaseAuth.prototype.getUserByPhoneNumber = function (phoneNumber) {
|
||||
return this.authRequestHandler.getAccountInfoByPhoneNumber(phoneNumber)
|
||||
.then(function (response) {
|
||||
// Returns the user record populated with server response.
|
||||
return new user_record_1.UserRecord(response.users[0]);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Exports a batch of user accounts. Batch size is determined by the maxResults argument.
|
||||
* Starting point of the batch is determined by the pageToken argument.
|
||||
*
|
||||
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
|
||||
* allowed limit.
|
||||
* @param {string=} pageToken The next page token. If not specified, returns users starting
|
||||
* without any offset.
|
||||
* @return {Promise<{users: UserRecord[], pageToken?: string}>} A promise that resolves with
|
||||
* the current batch of downloaded users and the next page token. For the last page, an
|
||||
* empty list of users and no page token are returned.
|
||||
*/
|
||||
BaseAuth.prototype.listUsers = function (maxResults, pageToken) {
|
||||
return this.authRequestHandler.downloadAccount(maxResults, pageToken)
|
||||
.then(function (response) {
|
||||
// List of users to return.
|
||||
var users = [];
|
||||
// Convert each user response to a UserRecord.
|
||||
response.users.forEach(function (userResponse) {
|
||||
users.push(new user_record_1.UserRecord(userResponse));
|
||||
});
|
||||
// Return list of user records and the next page token if available.
|
||||
var result = {
|
||||
users: users,
|
||||
pageToken: response.nextPageToken,
|
||||
};
|
||||
// Delete result.pageToken if undefined.
|
||||
if (typeof result.pageToken === 'undefined') {
|
||||
delete result.pageToken;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Creates a new user with the properties provided.
|
||||
*
|
||||
* @param {CreateRequest} properties The properties to set on the new user record to be created.
|
||||
* @return {Promise<UserRecord>} A promise that resolves with the newly created user record.
|
||||
*/
|
||||
BaseAuth.prototype.createUser = function (properties) {
|
||||
var _this = this;
|
||||
return this.authRequestHandler.createNewAccount(properties)
|
||||
.then(function (uid) {
|
||||
// Return the corresponding user record.
|
||||
return _this.getUser(uid);
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.code === 'auth/user-not-found') {
|
||||
// Something must have happened after creating the user and then retrieving it.
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Unable to create the user record provided.');
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Deletes the user identified by the provided user id and returns a promise that is
|
||||
* fulfilled when the user is found and successfully deleted.
|
||||
*
|
||||
* @param {string} uid The uid of the user to delete.
|
||||
* @return {Promise<void>} A promise that resolves when the user is successfully deleted.
|
||||
*/
|
||||
BaseAuth.prototype.deleteUser = function (uid) {
|
||||
return this.authRequestHandler.deleteAccount(uid)
|
||||
.then(function (response) {
|
||||
// Return nothing on success.
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Updates an existing user with the properties provided.
|
||||
*
|
||||
* @param {string} uid The uid identifier of the user to update.
|
||||
* @param {UpdateRequest} properties The properties to update on the existing user.
|
||||
* @return {Promise<UserRecord>} A promise that resolves with the modified user record.
|
||||
*/
|
||||
BaseAuth.prototype.updateUser = function (uid, properties) {
|
||||
var _this = this;
|
||||
return this.authRequestHandler.updateExistingAccount(uid, properties)
|
||||
.then(function (existingUid) {
|
||||
// Return the corresponding user record.
|
||||
return _this.getUser(existingUid);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Sets additional developer claims on an existing user identified by the provided UID.
|
||||
*
|
||||
* @param {string} uid The user to edit.
|
||||
* @param {object} customUserClaims The developer claims to set.
|
||||
* @return {Promise<void>} A promise that resolves when the operation completes
|
||||
* successfully.
|
||||
*/
|
||||
BaseAuth.prototype.setCustomUserClaims = function (uid, customUserClaims) {
|
||||
return this.authRequestHandler.setCustomUserClaims(uid, customUserClaims)
|
||||
.then(function (existingUid) {
|
||||
// Return nothing on success.
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Revokes all refresh tokens for the specified user identified by the provided UID.
|
||||
* In addition to revoking all refresh tokens for a user, all ID tokens issued before
|
||||
* revocation will also be revoked on the Auth backend. Any request with an ID token
|
||||
* generated before revocation will be rejected with a token expired error.
|
||||
*
|
||||
* @param {string} uid The user whose tokens are to be revoked.
|
||||
* @return {Promise<void>} A promise that resolves when the operation completes
|
||||
* successfully.
|
||||
*/
|
||||
BaseAuth.prototype.revokeRefreshTokens = function (uid) {
|
||||
return this.authRequestHandler.revokeRefreshTokens(uid)
|
||||
.then(function (existingUid) {
|
||||
// Return nothing on success.
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Imports the list of users provided to Firebase Auth. This is useful when
|
||||
* migrating from an external authentication system without having to use the Firebase CLI SDK.
|
||||
* At most, 1000 users are allowed to be imported one at a time.
|
||||
* When importing a list of password users, UserImportOptions are required to be specified.
|
||||
*
|
||||
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
|
||||
* @param {UserImportOptions=} options The user import options, required when the users provided
|
||||
* include password credentials.
|
||||
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
|
||||
* with the result of the import. This includes the number of successful imports, the number
|
||||
* of failed uploads and their corresponding errors.
|
||||
*/
|
||||
BaseAuth.prototype.importUsers = function (users, options) {
|
||||
return this.authRequestHandler.uploadAccount(users, options);
|
||||
};
|
||||
/**
|
||||
* Creates a new Firebase session cookie with the specified options that can be used for
|
||||
* session management (set as a server side session cookie with custom cookie policy).
|
||||
* The session cookie JWT will have the same payload claims as the provided ID token.
|
||||
*
|
||||
* @param {string} idToken The Firebase ID token to exchange for a session cookie.
|
||||
* @param {SessionCookieOptions} sessionCookieOptions The session cookie options which includes
|
||||
* custom session duration.
|
||||
*
|
||||
* @return {Promise<string>} A promise that resolves on success with the created session cookie.
|
||||
*/
|
||||
BaseAuth.prototype.createSessionCookie = function (idToken, sessionCookieOptions) {
|
||||
// Return rejected promise if expiresIn is not available.
|
||||
if (!validator.isNonNullObject(sessionCookieOptions) ||
|
||||
!validator.isNumber(sessionCookieOptions.expiresIn)) {
|
||||
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION));
|
||||
}
|
||||
return this.authRequestHandler.createSessionCookie(idToken, sessionCookieOptions.expiresIn);
|
||||
};
|
||||
/**
|
||||
* Verifies a Firebase session cookie. Returns a Promise with the tokens claims. Rejects
|
||||
* the promise if the token could not be verified. If checkRevoked is set to true,
|
||||
* verifies if the session corresponding to the session cookie was revoked. If the corresponding
|
||||
* user's session was invalidated, an auth/session-cookie-revoked error is thrown. If not
|
||||
* specified the check is not performed.
|
||||
*
|
||||
* @param {string} sessionCookie The session cookie to verify.
|
||||
* @param {boolean=} checkRevoked Whether to check if the session cookie is revoked.
|
||||
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
|
||||
* verification.
|
||||
*/
|
||||
BaseAuth.prototype.verifySessionCookie = function (sessionCookie, checkRevoked) {
|
||||
var _this = this;
|
||||
if (checkRevoked === void 0) { checkRevoked = false; }
|
||||
return this.sessionCookieVerifier.verifyJWT(sessionCookie)
|
||||
.then(function (decodedIdToken) {
|
||||
// Whether to check if the token was revoked.
|
||||
if (!checkRevoked) {
|
||||
return decodedIdToken;
|
||||
}
|
||||
return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.SESSION_COOKIE_REVOKED);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Generates the out of band email action link for password reset flows for the
|
||||
* email specified using the action code settings provided.
|
||||
* Returns a promise that resolves with the generated link.
|
||||
*
|
||||
* @param {string} email The email of the user whose password is to be reset.
|
||||
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
|
||||
* the link is to be handled by a mobile app and the additional state information to be passed in the
|
||||
* deep link, etc.
|
||||
* @return {Promise<string>} A promise that resolves with the password reset link.
|
||||
*/
|
||||
BaseAuth.prototype.generatePasswordResetLink = function (email, actionCodeSettings) {
|
||||
return this.authRequestHandler.getEmailActionLink('PASSWORD_RESET', email, actionCodeSettings);
|
||||
};
|
||||
/**
|
||||
* Generates the out of band email action link for email verification flows for the
|
||||
* email specified using the action code settings provided.
|
||||
* Returns a promise that resolves with the generated link.
|
||||
*
|
||||
* @param {string} email The email of the user to be verified.
|
||||
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
|
||||
* the link is to be handled by a mobile app and the additional state information to be passed in the
|
||||
* deep link, etc.
|
||||
* @return {Promise<string>} A promise that resolves with the email verification link.
|
||||
*/
|
||||
BaseAuth.prototype.generateEmailVerificationLink = function (email, actionCodeSettings) {
|
||||
return this.authRequestHandler.getEmailActionLink('VERIFY_EMAIL', email, actionCodeSettings);
|
||||
};
|
||||
/**
|
||||
* Generates the out of band email action link for email link sign-in flows for the
|
||||
* email specified using the action code settings provided.
|
||||
* Returns a promise that resolves with the generated link.
|
||||
*
|
||||
* @param {string} email The email of the user signing in.
|
||||
* @param {ActionCodeSettings} actionCodeSettings The required action code setings which defines whether
|
||||
* the link is to be handled by a mobile app and the additional state information to be passed in the
|
||||
* deep link, etc.
|
||||
* @return {Promise<string>} A promise that resolves with the email sign-in link.
|
||||
*/
|
||||
BaseAuth.prototype.generateSignInWithEmailLink = function (email, actionCodeSettings) {
|
||||
return this.authRequestHandler.getEmailActionLink('EMAIL_SIGNIN', email, actionCodeSettings);
|
||||
};
|
||||
/**
|
||||
* Verifies the decoded Firebase issued JWT is not revoked. Returns a promise that resolves
|
||||
* with the decoded claims on success. Rejects the promise with revocation error if revoked.
|
||||
*
|
||||
* @param {DecodedIdToken} decodedIdToken The JWT's decoded claims.
|
||||
* @param {ErrorInfo} revocationErrorInfo The revocation error info to throw on revocation
|
||||
* detection.
|
||||
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
|
||||
* verification.
|
||||
*/
|
||||
BaseAuth.prototype.verifyDecodedJWTNotRevoked = function (decodedIdToken, revocationErrorInfo) {
|
||||
// Get tokens valid after time for the corresponding user.
|
||||
return this.getUser(decodedIdToken.sub)
|
||||
.then(function (user) {
|
||||
// If no tokens valid after time available, token is not revoked.
|
||||
if (user.tokensValidAfterTime) {
|
||||
// Get the ID token authentication time and convert to milliseconds UTC.
|
||||
var authTimeUtc = decodedIdToken.auth_time * 1000;
|
||||
// Get user tokens valid after time in milliseconds UTC.
|
||||
var validSinceUtc = new Date(user.tokensValidAfterTime).getTime();
|
||||
// Check if authentication time is older than valid since time.
|
||||
if (authTimeUtc < validSinceUtc) {
|
||||
throw new error_1.FirebaseAuthError(revocationErrorInfo);
|
||||
}
|
||||
}
|
||||
// All checks above passed. Return the decoded token.
|
||||
return decodedIdToken;
|
||||
});
|
||||
};
|
||||
return BaseAuth;
|
||||
}());
|
||||
/**
|
||||
* Auth service bound to the provided app.
|
||||
*/
|
||||
var Auth = /** @class */ (function (_super) {
|
||||
__extends(Auth, _super);
|
||||
/**
|
||||
* @param {object} app The app for this Auth service.
|
||||
* @constructor
|
||||
*/
|
||||
function Auth(app) {
|
||||
var _this = _super.call(this, Auth.getProjectId(app), new auth_api_request_1.FirebaseAuthRequestHandler(app), token_generator_1.cryptoSignerFromApp(app)) || this;
|
||||
_this.INTERNAL = new AuthInternals();
|
||||
_this.app_ = app;
|
||||
return _this;
|
||||
}
|
||||
/**
|
||||
* Returns the FirebaseApp's project ID.
|
||||
*
|
||||
* @param {FirebaseApp} app The project ID for an app.
|
||||
* @return {string} The FirebaseApp's project ID.
|
||||
*/
|
||||
Auth.getProjectId = function (app) {
|
||||
if (typeof app !== 'object' || app === null || !('options' in app)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.auth() must be a valid Firebase app instance.');
|
||||
}
|
||||
return utils.getProjectId(app);
|
||||
};
|
||||
Object.defineProperty(Auth.prototype, "app", {
|
||||
/**
|
||||
* Returns the app associated with this Auth instance.
|
||||
*
|
||||
* @return {FirebaseApp} The app associated with this Auth instance.
|
||||
*/
|
||||
get: function () {
|
||||
return this.app_;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return Auth;
|
||||
}(BaseAuth));
|
||||
exports.Auth = Auth;
|
304
express-server/node_modules/firebase-admin/lib/auth/credential.js
generated
vendored
Normal file
304
express-server/node_modules/firebase-admin/lib/auth/credential.js
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
/*! firebase-admin v6.4.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2017 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 });
|
||||
// Use untyped import syntax for Node built-ins
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var error_1 = require("../utils/error");
|
||||
var api_request_1 = require("../utils/api-request");
|
||||
var GOOGLE_TOKEN_AUDIENCE = 'https://accounts.google.com/o/oauth2/token';
|
||||
var GOOGLE_AUTH_TOKEN_HOST = 'accounts.google.com';
|
||||
var GOOGLE_AUTH_TOKEN_PATH = '/o/oauth2/token';
|
||||
// NOTE: the Google Metadata Service uses HTTP over a vlan
|
||||
var GOOGLE_METADATA_SERVICE_HOST = 'metadata.google.internal';
|
||||
var GOOGLE_METADATA_SERVICE_PATH = '/computeMetadata/v1beta1/instance/service-accounts/default/token';
|
||||
var configDir = (function () {
|
||||
// Windows has a dedicated low-rights location for apps at ~/Application Data
|
||||
var sys = os.platform();
|
||||
if (sys && sys.length >= 3 && sys.substring(0, 3).toLowerCase() === 'win') {
|
||||
return process.env.APPDATA;
|
||||
}
|
||||
// On *nix the gcloud cli creates a . dir.
|
||||
return process.env.HOME && path.resolve(process.env.HOME, '.config');
|
||||
})();
|
||||
var GCLOUD_CREDENTIAL_SUFFIX = 'gcloud/application_default_credentials.json';
|
||||
var GCLOUD_CREDENTIAL_PATH = configDir && path.resolve(configDir, GCLOUD_CREDENTIAL_SUFFIX);
|
||||
var REFRESH_TOKEN_HOST = 'www.googleapis.com';
|
||||
var REFRESH_TOKEN_PATH = '/oauth2/v4/token';
|
||||
var ONE_HOUR_IN_SECONDS = 60 * 60;
|
||||
var JWT_ALGORITHM = 'RS256';
|
||||
function copyAttr(to, from, key, alt) {
|
||||
var tmp = from[key] || from[alt];
|
||||
if (typeof tmp !== 'undefined') {
|
||||
to[key] = tmp;
|
||||
}
|
||||
}
|
||||
var RefreshToken = /** @class */ (function () {
|
||||
function RefreshToken(json) {
|
||||
copyAttr(this, json, 'clientId', 'client_id');
|
||||
copyAttr(this, json, 'clientSecret', 'client_secret');
|
||||
copyAttr(this, json, 'refreshToken', 'refresh_token');
|
||||
copyAttr(this, json, 'type', 'type');
|
||||
var errorMessage;
|
||||
if (typeof this.clientId !== 'string' || !this.clientId) {
|
||||
errorMessage = 'Refresh token must contain a "client_id" property.';
|
||||
}
|
||||
else if (typeof this.clientSecret !== 'string' || !this.clientSecret) {
|
||||
errorMessage = 'Refresh token must contain a "client_secret" property.';
|
||||
}
|
||||
else if (typeof this.refreshToken !== 'string' || !this.refreshToken) {
|
||||
errorMessage = 'Refresh token must contain a "refresh_token" property.';
|
||||
}
|
||||
else if (typeof this.type !== 'string' || !this.type) {
|
||||
errorMessage = 'Refresh token must contain a "type" property.';
|
||||
}
|
||||
if (typeof errorMessage !== 'undefined') {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Tries to load a RefreshToken from a path. If the path is not present, returns null.
|
||||
* Throws if data at the path is invalid.
|
||||
*/
|
||||
RefreshToken.fromPath = function (filePath) {
|
||||
var jsonString;
|
||||
try {
|
||||
jsonString = fs.readFileSync(filePath, 'utf8');
|
||||
}
|
||||
catch (ignored) {
|
||||
// Ignore errors if the file is not present, as this is sometimes an expected condition
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new RefreshToken(JSON.parse(jsonString));
|
||||
}
|
||||
catch (error) {
|
||||
// Throw a nicely formed error message if the file contents cannot be parsed
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse refresh token file: ' + error);
|
||||
}
|
||||
};
|
||||
return RefreshToken;
|
||||
}());
|
||||
exports.RefreshToken = RefreshToken;
|
||||
/**
|
||||
* A struct containing the properties necessary to use service-account JSON credentials.
|
||||
*/
|
||||
var Certificate = /** @class */ (function () {
|
||||
function Certificate(json) {
|
||||
if (typeof json !== 'object' || json === null) {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Certificate object must be an object.');
|
||||
}
|
||||
copyAttr(this, json, 'projectId', 'project_id');
|
||||
copyAttr(this, json, 'privateKey', 'private_key');
|
||||
copyAttr(this, json, 'clientEmail', 'client_email');
|
||||
var errorMessage;
|
||||
if (typeof this.privateKey !== 'string' || !this.privateKey) {
|
||||
errorMessage = 'Certificate object must contain a string "private_key" property.';
|
||||
}
|
||||
else if (typeof this.clientEmail !== 'string' || !this.clientEmail) {
|
||||
errorMessage = 'Certificate object must contain a string "client_email" property.';
|
||||
}
|
||||
if (typeof errorMessage !== 'undefined') {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
|
||||
}
|
||||
var forge = require('node-forge');
|
||||
try {
|
||||
forge.pki.privateKeyFromPem(this.privateKey);
|
||||
}
|
||||
catch (error) {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse private key: ' + error);
|
||||
}
|
||||
}
|
||||
Certificate.fromPath = function (filePath) {
|
||||
// Node bug encountered in v6.x. fs.readFileSync hangs when path is a 0 or 1.
|
||||
if (typeof filePath !== 'string') {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse certificate key file: TypeError: path must be a string');
|
||||
}
|
||||
try {
|
||||
return new Certificate(JSON.parse(fs.readFileSync(filePath, 'utf8')));
|
||||
}
|
||||
catch (error) {
|
||||
// Throw a nicely formed error message if the file contents cannot be parsed
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse certificate key file: ' + error);
|
||||
}
|
||||
};
|
||||
return Certificate;
|
||||
}());
|
||||
exports.Certificate = Certificate;
|
||||
/**
|
||||
* Obtain a new OAuth2 token by making a remote service call.
|
||||
*/
|
||||
function requestAccessToken(client, request) {
|
||||
return client.send(request).then(function (resp) {
|
||||
var json = resp.data;
|
||||
if (json.error) {
|
||||
var errorMessage = 'Error fetching access token: ' + json.error;
|
||||
if (json.error_description) {
|
||||
errorMessage += ' (' + json.error_description + ')';
|
||||
}
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
|
||||
}
|
||||
else if (!json.access_token || !json.expires_in) {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, "Unexpected response while fetching access token: " + JSON.stringify(json));
|
||||
}
|
||||
else {
|
||||
return json;
|
||||
}
|
||||
}).catch(function (err) {
|
||||
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, "Failed to parse access token response: " + err.toString());
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Implementation of Credential that uses a service account certificate.
|
||||
*/
|
||||
var CertCredential = /** @class */ (function () {
|
||||
function CertCredential(serviceAccountPathOrObject, httpAgent) {
|
||||
this.certificate = (typeof serviceAccountPathOrObject === 'string') ?
|
||||
Certificate.fromPath(serviceAccountPathOrObject) : new Certificate(serviceAccountPathOrObject);
|
||||
this.httpClient = new api_request_1.HttpClient();
|
||||
this.httpAgent = httpAgent;
|
||||
}
|
||||
CertCredential.prototype.getAccessToken = function () {
|
||||
var token = this.createAuthJwt_();
|
||||
var postData = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3A' +
|
||||
'grant-type%3Ajwt-bearer&assertion=' + token;
|
||||
var request = {
|
||||
method: 'POST',
|
||||
url: "https://" + GOOGLE_AUTH_TOKEN_HOST + GOOGLE_AUTH_TOKEN_PATH,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
data: postData,
|
||||
httpAgent: this.httpAgent,
|
||||
};
|
||||
return requestAccessToken(this.httpClient, request);
|
||||
};
|
||||
CertCredential.prototype.getCertificate = function () {
|
||||
return this.certificate;
|
||||
};
|
||||
CertCredential.prototype.createAuthJwt_ = function () {
|
||||
var claims = {
|
||||
scope: [
|
||||
'https://www.googleapis.com/auth/cloud-platform',
|
||||
'https://www.googleapis.com/auth/firebase.database',
|
||||
'https://www.googleapis.com/auth/firebase.messaging',
|
||||
'https://www.googleapis.com/auth/identitytoolkit',
|
||||
'https://www.googleapis.com/auth/userinfo.email',
|
||||
].join(' '),
|
||||
};
|
||||
var jwt = require('jsonwebtoken');
|
||||
// This method is actually synchronous so we can capture and return the buffer.
|
||||
return jwt.sign(claims, this.certificate.privateKey, {
|
||||
audience: GOOGLE_TOKEN_AUDIENCE,
|
||||
expiresIn: ONE_HOUR_IN_SECONDS,
|
||||
issuer: this.certificate.clientEmail,
|
||||
algorithm: JWT_ALGORITHM,
|
||||
});
|
||||
};
|
||||
return CertCredential;
|
||||
}());
|
||||
exports.CertCredential = CertCredential;
|
||||
/**
|
||||
* Implementation of Credential that gets access tokens from refresh tokens.
|
||||
*/
|
||||
var RefreshTokenCredential = /** @class */ (function () {
|
||||
function RefreshTokenCredential(refreshTokenPathOrObject, httpAgent) {
|
||||
this.refreshToken = (typeof refreshTokenPathOrObject === 'string') ?
|
||||
RefreshToken.fromPath(refreshTokenPathOrObject) : new RefreshToken(refreshTokenPathOrObject);
|
||||
this.httpClient = new api_request_1.HttpClient();
|
||||
this.httpAgent = httpAgent;
|
||||
}
|
||||
RefreshTokenCredential.prototype.getAccessToken = function () {
|
||||
var postData = 'client_id=' + this.refreshToken.clientId + '&' +
|
||||
'client_secret=' + this.refreshToken.clientSecret + '&' +
|
||||
'refresh_token=' + this.refreshToken.refreshToken + '&' +
|
||||
'grant_type=refresh_token';
|
||||
var request = {
|
||||
method: 'POST',
|
||||
url: "https://" + REFRESH_TOKEN_HOST + REFRESH_TOKEN_PATH,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
data: postData,
|
||||
httpAgent: this.httpAgent,
|
||||
};
|
||||
return requestAccessToken(this.httpClient, request);
|
||||
};
|
||||
RefreshTokenCredential.prototype.getCertificate = function () {
|
||||
return null;
|
||||
};
|
||||
return RefreshTokenCredential;
|
||||
}());
|
||||
exports.RefreshTokenCredential = RefreshTokenCredential;
|
||||
/**
|
||||
* Implementation of Credential that gets access tokens from the metadata service available
|
||||
* in the Google Cloud Platform. This authenticates the process as the default service account
|
||||
* of an App Engine instance or Google Compute Engine machine.
|
||||
*/
|
||||
var MetadataServiceCredential = /** @class */ (function () {
|
||||
function MetadataServiceCredential(httpAgent) {
|
||||
this.httpClient = new api_request_1.HttpClient();
|
||||
this.httpAgent = httpAgent;
|
||||
}
|
||||
MetadataServiceCredential.prototype.getAccessToken = function () {
|
||||
var request = {
|
||||
method: 'GET',
|
||||
url: "http://" + GOOGLE_METADATA_SERVICE_HOST + GOOGLE_METADATA_SERVICE_PATH,
|
||||
httpAgent: this.httpAgent,
|
||||
};
|
||||
return requestAccessToken(this.httpClient, request);
|
||||
};
|
||||
MetadataServiceCredential.prototype.getCertificate = function () {
|
||||
return null;
|
||||
};
|
||||
return MetadataServiceCredential;
|
||||
}());
|
||||
exports.MetadataServiceCredential = MetadataServiceCredential;
|
||||
/**
|
||||
* ApplicationDefaultCredential implements the process for loading credentials as
|
||||
* described in https://developers.google.com/identity/protocols/application-default-credentials
|
||||
*/
|
||||
var ApplicationDefaultCredential = /** @class */ (function () {
|
||||
function ApplicationDefaultCredential(httpAgent) {
|
||||
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
||||
var serviceAccount = Certificate.fromPath(process.env.GOOGLE_APPLICATION_CREDENTIALS);
|
||||
this.credential_ = new CertCredential(serviceAccount, httpAgent);
|
||||
return;
|
||||
}
|
||||
// It is OK to not have this file. If it is present, it must be valid.
|
||||
var refreshToken = RefreshToken.fromPath(GCLOUD_CREDENTIAL_PATH);
|
||||
if (refreshToken) {
|
||||
this.credential_ = new RefreshTokenCredential(refreshToken, httpAgent);
|
||||
return;
|
||||
}
|
||||
this.credential_ = new MetadataServiceCredential(httpAgent);
|
||||
}
|
||||
ApplicationDefaultCredential.prototype.getAccessToken = function () {
|
||||
return this.credential_.getAccessToken();
|
||||
};
|
||||
ApplicationDefaultCredential.prototype.getCertificate = function () {
|
||||
return this.credential_.getCertificate();
|
||||
};
|
||||
// Used in testing to verify we are delegating to the correct implementation.
|
||||
ApplicationDefaultCredential.prototype.getCredential = function () {
|
||||
return this.credential_;
|
||||
};
|
||||
return ApplicationDefaultCredential;
|
||||
}());
|
||||
exports.ApplicationDefaultCredential = ApplicationDefaultCredential;
|
252
express-server/node_modules/firebase-admin/lib/auth/token-generator.js
generated
vendored
Normal file
252
express-server/node_modules/firebase-admin/lib/auth/token-generator.js
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
/*! firebase-admin v6.4.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2017 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 api_request_1 = require("../utils/api-request");
|
||||
var validator = require("../utils/validator");
|
||||
var utils_1 = require("../utils");
|
||||
var ALGORITHM_RS256 = 'RS256';
|
||||
var ONE_HOUR_IN_SECONDS = 60 * 60;
|
||||
// List of blacklisted claims which cannot be provided when creating a custom token
|
||||
var BLACKLISTED_CLAIMS = [
|
||||
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat', 'iss', 'jti',
|
||||
'nbf', 'nonce',
|
||||
];
|
||||
// Audience to use for Firebase Auth Custom tokens
|
||||
var FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
|
||||
/**
|
||||
* A CryptoSigner implementation that uses an explicitly specified service account private key to
|
||||
* sign data. Performs all operations locally, and does not make any RPC calls.
|
||||
*/
|
||||
var ServiceAccountSigner = /** @class */ (function () {
|
||||
/**
|
||||
* Creates a new CryptoSigner instance from the given service account certificate.
|
||||
*
|
||||
* @param {Certificate} certificate A service account certificate.
|
||||
*/
|
||||
function ServiceAccountSigner(certificate) {
|
||||
if (!certificate) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a certificate to initialize ServiceAccountSigner.');
|
||||
}
|
||||
if (!validator.isNonEmptyString(certificate.clientEmail) || !validator.isNonEmptyString(certificate.privateKey)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a certificate with validate clientEmail and privateKey to ' +
|
||||
'initialize ServiceAccountSigner.');
|
||||
}
|
||||
this.certificate = certificate;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ServiceAccountSigner.prototype.sign = function (buffer) {
|
||||
var crypto = require('crypto');
|
||||
var sign = crypto.createSign('RSA-SHA256');
|
||||
sign.update(buffer);
|
||||
return Promise.resolve(sign.sign(this.certificate.privateKey));
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ServiceAccountSigner.prototype.getAccountId = function () {
|
||||
return Promise.resolve(this.certificate.clientEmail);
|
||||
};
|
||||
return ServiceAccountSigner;
|
||||
}());
|
||||
exports.ServiceAccountSigner = ServiceAccountSigner;
|
||||
/**
|
||||
* A CryptoSigner implementation that uses the remote IAM service to sign data. If initialized without
|
||||
* a service account ID, attempts to discover a service account ID by consulting the local Metadata
|
||||
* service. This will succeed in managed environments like Google Cloud Functions and App Engine.
|
||||
*
|
||||
* @see https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signBlob
|
||||
* @see https://cloud.google.com/compute/docs/storing-retrieving-metadata
|
||||
*/
|
||||
var IAMSigner = /** @class */ (function () {
|
||||
function IAMSigner(httpClient, serviceAccountId) {
|
||||
if (!httpClient) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'INTERNAL ASSERT: Must provide a HTTP client to initialize IAMSigner.');
|
||||
}
|
||||
if (typeof serviceAccountId !== 'undefined' && !validator.isNonEmptyString(serviceAccountId)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'INTERNAL ASSERT: Service account ID must be undefined or a non-empty string.');
|
||||
}
|
||||
this.httpClient = httpClient;
|
||||
this.serviceAccountId = serviceAccountId;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
IAMSigner.prototype.sign = function (buffer) {
|
||||
var _this = this;
|
||||
return this.getAccountId().then(function (serviceAccount) {
|
||||
var request = {
|
||||
method: 'POST',
|
||||
url: "https://iam.googleapis.com/v1/projects/-/serviceAccounts/" + serviceAccount + ":signBlob",
|
||||
data: { bytesToSign: buffer.toString('base64') },
|
||||
};
|
||||
return _this.httpClient.send(request);
|
||||
}).then(function (response) {
|
||||
// Response from IAM is base64 encoded. Decode it into a buffer and return.
|
||||
return Buffer.from(response.data.signature, 'base64');
|
||||
}).catch(function (err) {
|
||||
if (err instanceof api_request_1.HttpError) {
|
||||
var error = err.response.data;
|
||||
var errorCode = void 0;
|
||||
var errorMsg = void 0;
|
||||
if (validator.isNonNullObject(error) && error.error) {
|
||||
errorCode = error.error.status || null;
|
||||
var description = 'Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens ' +
|
||||
'for more details on how to use and troubleshoot this feature.';
|
||||
errorMsg = error.error.message + "; " + description || null;
|
||||
}
|
||||
throw error_1.FirebaseAuthError.fromServerError(errorCode, errorMsg, error);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
IAMSigner.prototype.getAccountId = function () {
|
||||
var _this = this;
|
||||
if (validator.isNonEmptyString(this.serviceAccountId)) {
|
||||
return Promise.resolve(this.serviceAccountId);
|
||||
}
|
||||
var request = {
|
||||
method: 'GET',
|
||||
url: 'http://metadata/computeMetadata/v1/instance/service-accounts/default/email',
|
||||
headers: {
|
||||
'Metadata-Flavor': 'Google',
|
||||
},
|
||||
};
|
||||
var client = new api_request_1.HttpClient();
|
||||
return client.send(request).then(function (response) {
|
||||
_this.serviceAccountId = response.text;
|
||||
return _this.serviceAccountId;
|
||||
}).catch(function (err) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, "Failed to determine service account. Make sure to initialize " +
|
||||
"the SDK with a service account credential. Alternatively specify a service " +
|
||||
("account with iam.serviceAccounts.signBlob permission. Original error: " + err));
|
||||
});
|
||||
};
|
||||
return IAMSigner;
|
||||
}());
|
||||
exports.IAMSigner = IAMSigner;
|
||||
/**
|
||||
* Create a new CryptoSigner instance for the given app. If the app has been initialized with a service
|
||||
* account credential, creates a ServiceAccountSigner. Otherwise creates an IAMSigner.
|
||||
*
|
||||
* @param {FirebaseApp} app A FirebaseApp instance.
|
||||
* @return {CryptoSigner} A CryptoSigner instance.
|
||||
*/
|
||||
function cryptoSignerFromApp(app) {
|
||||
var cert = app.options.credential.getCertificate();
|
||||
if (cert != null && validator.isNonEmptyString(cert.privateKey) && validator.isNonEmptyString(cert.clientEmail)) {
|
||||
return new ServiceAccountSigner(cert);
|
||||
}
|
||||
return new IAMSigner(new api_request_1.AuthorizedHttpClient(app), app.options.serviceAccountId);
|
||||
}
|
||||
exports.cryptoSignerFromApp = cryptoSignerFromApp;
|
||||
/**
|
||||
* Class for generating different types of Firebase Auth tokens (JWTs).
|
||||
*/
|
||||
var FirebaseTokenGenerator = /** @class */ (function () {
|
||||
function FirebaseTokenGenerator(signer) {
|
||||
if (!validator.isNonNullObject(signer)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a CryptoSigner to use FirebaseTokenGenerator.');
|
||||
}
|
||||
this.signer = signer;
|
||||
}
|
||||
/**
|
||||
* Creates a new Firebase Auth Custom token.
|
||||
*
|
||||
* @param {string} uid The user ID to use for the generated Firebase Auth Custom token.
|
||||
* @param {object} [developerClaims] Optional developer claims to include in the generated Firebase
|
||||
* Auth Custom token.
|
||||
* @return {Promise<string>} A Promise fulfilled with a Firebase Auth Custom token signed with a
|
||||
* service account key and containing the provided payload.
|
||||
*/
|
||||
FirebaseTokenGenerator.prototype.createCustomToken = function (uid, developerClaims) {
|
||||
var _this = this;
|
||||
var errorMessage;
|
||||
if (typeof uid !== 'string' || uid === '') {
|
||||
errorMessage = 'First argument to createCustomToken() must be a non-empty string uid.';
|
||||
}
|
||||
else if (uid.length > 128) {
|
||||
errorMessage = 'First argument to createCustomToken() must a uid with less than or equal to 128 characters.';
|
||||
}
|
||||
else if (!this.isDeveloperClaimsValid_(developerClaims)) {
|
||||
errorMessage = 'Second argument to createCustomToken() must be an object containing the developer claims.';
|
||||
}
|
||||
if (typeof errorMessage !== 'undefined') {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
|
||||
}
|
||||
var claims = {};
|
||||
if (typeof developerClaims !== 'undefined') {
|
||||
for (var key in developerClaims) {
|
||||
/* istanbul ignore else */
|
||||
if (developerClaims.hasOwnProperty(key)) {
|
||||
if (BLACKLISTED_CLAIMS.indexOf(key) !== -1) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Developer claim \"" + key + "\" is reserved and cannot be specified.");
|
||||
}
|
||||
claims[key] = developerClaims[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.signer.getAccountId().then(function (account) {
|
||||
var header = {
|
||||
alg: ALGORITHM_RS256,
|
||||
typ: 'JWT',
|
||||
};
|
||||
var iat = Math.floor(Date.now() / 1000);
|
||||
var body = {
|
||||
aud: FIREBASE_AUDIENCE,
|
||||
iat: iat,
|
||||
exp: iat + ONE_HOUR_IN_SECONDS,
|
||||
iss: account,
|
||||
sub: account,
|
||||
uid: uid,
|
||||
};
|
||||
if (Object.keys(claims).length > 0) {
|
||||
body.claims = claims;
|
||||
}
|
||||
var token = _this.encodeSegment(header) + "." + _this.encodeSegment(body);
|
||||
var signPromise = _this.signer.sign(Buffer.from(token));
|
||||
return Promise.all([token, signPromise]);
|
||||
}).then(function (_a) {
|
||||
var token = _a[0], signature = _a[1];
|
||||
return token + "." + _this.encodeSegment(signature);
|
||||
});
|
||||
};
|
||||
FirebaseTokenGenerator.prototype.encodeSegment = function (segment) {
|
||||
var buffer = (segment instanceof Buffer) ? segment : Buffer.from(JSON.stringify(segment));
|
||||
return utils_1.toWebSafeBase64(buffer).replace(/\=+$/, '');
|
||||
};
|
||||
/**
|
||||
* Returns whether or not the provided developer claims are valid.
|
||||
*
|
||||
* @param {object} [developerClaims] Optional developer claims to validate.
|
||||
* @return {boolean} True if the provided claims are valid; otherwise, false.
|
||||
*/
|
||||
FirebaseTokenGenerator.prototype.isDeveloperClaimsValid_ = function (developerClaims) {
|
||||
if (typeof developerClaims === 'undefined') {
|
||||
return true;
|
||||
}
|
||||
return validator.isNonNullObject(developerClaims);
|
||||
};
|
||||
return FirebaseTokenGenerator;
|
||||
}());
|
||||
exports.FirebaseTokenGenerator = FirebaseTokenGenerator;
|
281
express-server/node_modules/firebase-admin/lib/auth/token-verifier.js
generated
vendored
Normal file
281
express-server/node_modules/firebase-admin/lib/auth/token-verifier.js
generated
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
/*! firebase-admin v6.4.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");
|
||||
var api_request_1 = require("../utils/api-request");
|
||||
// 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);
|
||||
}
|
||||
var client = new api_request_1.HttpClient();
|
||||
var request = {
|
||||
method: 'GET',
|
||||
url: this.clientCertUrl,
|
||||
};
|
||||
return client.send(request).then(function (resp) {
|
||||
if (!resp.isJson() || resp.data.error) {
|
||||
// Treat all non-json messages and messages with an 'error' field as
|
||||
// error responses.
|
||||
throw new api_request_1.HttpError(resp);
|
||||
}
|
||||
if (resp.headers.hasOwnProperty('cache-control')) {
|
||||
var cacheControlHeader = resp.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 = resp.data;
|
||||
return resp.data;
|
||||
}).catch(function (err) {
|
||||
if (err instanceof api_request_1.HttpError) {
|
||||
var errorMessage = 'Error fetching public keys for Google certs: ';
|
||||
var resp = err.response;
|
||||
if (resp.isJson() && resp.data.error) {
|
||||
errorMessage += "" + resp.data.error;
|
||||
if (resp.data.error_description) {
|
||||
errorMessage += ' (' + resp.data.error_description + ')';
|
||||
}
|
||||
}
|
||||
else {
|
||||
errorMessage += "" + resp.text;
|
||||
}
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, errorMessage);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
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;
|
316
express-server/node_modules/firebase-admin/lib/auth/user-import-builder.js
generated
vendored
Normal file
316
express-server/node_modules/firebase-admin/lib/auth/user-import-builder.js
generated
vendored
Normal file
@ -0,0 +1,316 @@
|
||||
/*! firebase-admin v6.4.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 deep_copy_1 = require("../utils/deep-copy");
|
||||
var utils = require("../utils");
|
||||
var validator = require("../utils/validator");
|
||||
var error_1 = require("../utils/error");
|
||||
/**
|
||||
* @param {any} obj The object to check for number field within.
|
||||
* @param {string} key The entry key.
|
||||
* @return {number|undefined} The corresponding number if available.
|
||||
*/
|
||||
function getNumberField(obj, key) {
|
||||
if (typeof obj[key] !== 'undefined' && obj[key] !== null) {
|
||||
return parseInt(obj[key].toString(), 10);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Converts a UserImportRecord to a UploadAccountUser object. Throws an error when invalid
|
||||
* fields are provided.
|
||||
* @param {UserImportRecord} user The UserImportRecord to conver to UploadAccountUser.
|
||||
* @param {ValidatorFunction=} userValidator The user validator function.
|
||||
* @return {UploadAccountUser} The corresponding UploadAccountUser to return.
|
||||
*/
|
||||
function populateUploadAccountUser(user, userValidator) {
|
||||
var result = {
|
||||
localId: user.uid,
|
||||
email: user.email,
|
||||
emailVerified: user.emailVerified,
|
||||
displayName: user.displayName,
|
||||
disabled: user.disabled,
|
||||
photoUrl: user.photoURL,
|
||||
phoneNumber: user.phoneNumber,
|
||||
providerUserInfo: [],
|
||||
customAttributes: user.customClaims && JSON.stringify(user.customClaims),
|
||||
};
|
||||
if (typeof user.passwordHash !== 'undefined') {
|
||||
if (!validator.isBuffer(user.passwordHash)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
|
||||
}
|
||||
result.passwordHash = utils.toWebSafeBase64(user.passwordHash);
|
||||
}
|
||||
if (typeof user.passwordSalt !== 'undefined') {
|
||||
if (!validator.isBuffer(user.passwordSalt)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
|
||||
}
|
||||
result.salt = utils.toWebSafeBase64(user.passwordSalt);
|
||||
}
|
||||
if (validator.isNonNullObject(user.metadata)) {
|
||||
if (validator.isNonEmptyString(user.metadata.creationTime)) {
|
||||
result.createdAt = new Date(user.metadata.creationTime).getTime();
|
||||
}
|
||||
if (validator.isNonEmptyString(user.metadata.lastSignInTime)) {
|
||||
result.lastLoginAt = new Date(user.metadata.lastSignInTime).getTime();
|
||||
}
|
||||
}
|
||||
if (validator.isArray(user.providerData)) {
|
||||
user.providerData.forEach(function (providerData) {
|
||||
result.providerUserInfo.push({
|
||||
providerId: providerData.providerId,
|
||||
rawId: providerData.uid,
|
||||
email: providerData.email,
|
||||
displayName: providerData.displayName,
|
||||
photoUrl: providerData.photoURL,
|
||||
});
|
||||
});
|
||||
}
|
||||
// Remove blank fields.
|
||||
var key;
|
||||
for (key in result) {
|
||||
if (typeof result[key] === 'undefined') {
|
||||
delete result[key];
|
||||
}
|
||||
}
|
||||
if (result.providerUserInfo.length === 0) {
|
||||
delete result.providerUserInfo;
|
||||
}
|
||||
// Validate the constructured user individual request. This will throw if an error
|
||||
// is detected.
|
||||
if (typeof userValidator === 'function') {
|
||||
userValidator(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Class that provides a helper for building/validating uploadAccount requests and
|
||||
* UserImportResult responses.
|
||||
*/
|
||||
var UserImportBuilder = /** @class */ (function () {
|
||||
/**
|
||||
* @param {UserImportRecord[]} users The list of user records to import.
|
||||
* @param {UserImportOptions=} options The import options which includes hashing
|
||||
* algorithm details.
|
||||
* @param {ValidatorFunction=} userRequestValidator The user request validator function.
|
||||
* @constructor
|
||||
*/
|
||||
function UserImportBuilder(users, options, userRequestValidator) {
|
||||
this.users = users;
|
||||
this.options = options;
|
||||
this.userRequestValidator = userRequestValidator;
|
||||
this.requiresHashOptions = false;
|
||||
this.validatedUsers = [];
|
||||
this.userImportResultErrors = [];
|
||||
this.indexMap = {};
|
||||
this.validatedUsers = this.populateUsers(this.users, this.userRequestValidator);
|
||||
this.validatedOptions = this.populateOptions(this.options, this.requiresHashOptions);
|
||||
}
|
||||
/**
|
||||
* Returns the corresponding constructed uploadAccount request.
|
||||
* @return {UploadAccountRequest} The constructed uploadAccount request.
|
||||
*/
|
||||
UserImportBuilder.prototype.buildRequest = function () {
|
||||
var users = this.validatedUsers.map(function (user) {
|
||||
return deep_copy_1.deepCopy(user);
|
||||
});
|
||||
return deep_copy_1.deepExtend({ users: users }, deep_copy_1.deepCopy(this.validatedOptions));
|
||||
};
|
||||
/**
|
||||
* Populates the UserImportResult using the client side detected errors and the server
|
||||
* side returned errors.
|
||||
* @return {UserImportResult} The user import result based on the returned failed
|
||||
* uploadAccount response.
|
||||
*/
|
||||
UserImportBuilder.prototype.buildResponse = function (failedUploads) {
|
||||
var _this = this;
|
||||
// Initialize user import result.
|
||||
var importResult = {
|
||||
successCount: this.users.length - this.userImportResultErrors.length,
|
||||
failureCount: this.userImportResultErrors.length,
|
||||
errors: deep_copy_1.deepCopy(this.userImportResultErrors),
|
||||
};
|
||||
importResult.failureCount += failedUploads.length;
|
||||
importResult.successCount -= failedUploads.length;
|
||||
failedUploads.forEach(function (failedUpload) {
|
||||
importResult.errors.push({
|
||||
// Map backend request index to original developer provided array index.
|
||||
index: _this.indexMap[failedUpload.index],
|
||||
error: new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_USER_IMPORT, failedUpload.message),
|
||||
});
|
||||
});
|
||||
// Sort errors by index.
|
||||
importResult.errors.sort(function (a, b) {
|
||||
return a.index - b.index;
|
||||
});
|
||||
// Return sorted result.
|
||||
return importResult;
|
||||
};
|
||||
/**
|
||||
* Validates and returns the hashing options of the uploadAccount request.
|
||||
* Throws an error whenever an invalid or missing options is detected.
|
||||
* @param {UserImportOptions} options The UserImportOptions.
|
||||
* @param {boolean} requiresHashOptions Whether to require hash options.
|
||||
* @return {UploadAccountOptions} The populated UploadAccount options.
|
||||
*/
|
||||
UserImportBuilder.prototype.populateOptions = function (options, requiresHashOptions) {
|
||||
var populatedOptions;
|
||||
if (!requiresHashOptions) {
|
||||
return {};
|
||||
}
|
||||
if (!validator.isNonNullObject(options.hash)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_HASH_ALGORITHM, "\"hash.algorithm\" is missing from the provided \"UserImportOptions\".");
|
||||
}
|
||||
if (typeof options.hash.algorithm === 'undefined' ||
|
||||
!validator.isNonEmptyString(options.hash.algorithm)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, "\"hash.algorithm\" must be a string matching the list of supported algorithms.");
|
||||
}
|
||||
var rounds;
|
||||
switch (options.hash.algorithm) {
|
||||
case 'HMAC_SHA512':
|
||||
case 'HMAC_SHA256':
|
||||
case 'HMAC_SHA1':
|
||||
case 'HMAC_MD5':
|
||||
if (!validator.isBuffer(options.hash.key)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, "A non-empty \"hash.key\" byte buffer must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
populatedOptions = {
|
||||
hashAlgorithm: options.hash.algorithm,
|
||||
signerKey: utils.toWebSafeBase64(options.hash.key),
|
||||
};
|
||||
break;
|
||||
case 'MD5':
|
||||
case 'SHA1':
|
||||
case 'SHA256':
|
||||
case 'SHA512':
|
||||
case 'PBKDF_SHA1':
|
||||
case 'PBKDF2_SHA256':
|
||||
rounds = getNumberField(options.hash, 'rounds');
|
||||
if (isNaN(rounds) || rounds < 0 || rounds > 120000) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, "A valid \"hash.rounds\" number between 0 and 120000 must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
populatedOptions = {
|
||||
hashAlgorithm: options.hash.algorithm,
|
||||
rounds: rounds,
|
||||
};
|
||||
break;
|
||||
case 'SCRYPT':
|
||||
if (!validator.isBuffer(options.hash.key)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, "A \"hash.key\" byte buffer must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
rounds = getNumberField(options.hash, 'rounds');
|
||||
if (isNaN(rounds) || rounds <= 0 || rounds > 8) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, "A valid \"hash.rounds\" number between 1 and 8 must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
var memoryCost = getNumberField(options.hash, 'memoryCost');
|
||||
if (isNaN(memoryCost) || memoryCost <= 0 || memoryCost > 14) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, "A valid \"hash.memoryCost\" number between 1 and 14 must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
if (typeof options.hash.saltSeparator !== 'undefined' &&
|
||||
!validator.isBuffer(options.hash.saltSeparator)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR, "\"hash.saltSeparator\" must be a byte buffer.");
|
||||
}
|
||||
populatedOptions = {
|
||||
hashAlgorithm: options.hash.algorithm,
|
||||
signerKey: utils.toWebSafeBase64(options.hash.key),
|
||||
rounds: rounds,
|
||||
memoryCost: memoryCost,
|
||||
saltSeparator: utils.toWebSafeBase64(options.hash.saltSeparator || Buffer.from('')),
|
||||
};
|
||||
break;
|
||||
case 'BCRYPT':
|
||||
populatedOptions = {
|
||||
hashAlgorithm: options.hash.algorithm,
|
||||
};
|
||||
break;
|
||||
case 'STANDARD_SCRYPT':
|
||||
var cpuMemCost = getNumberField(options.hash, 'memoryCost');
|
||||
if (isNaN(cpuMemCost)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, "A valid \"hash.memoryCost\" number must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
var parallelization = getNumberField(options.hash, 'parallelization');
|
||||
if (isNaN(parallelization)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_PARALLELIZATION, "A valid \"hash.parallelization\" number must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
var blockSize = getNumberField(options.hash, 'blockSize');
|
||||
if (isNaN(blockSize)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE, "A valid \"hash.blockSize\" number must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
var dkLen = getNumberField(options.hash, 'derivedKeyLength');
|
||||
if (isNaN(dkLen)) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH, "A valid \"hash.derivedKeyLength\" number must be provided for " +
|
||||
("hash algorithm " + options.hash.algorithm + "."));
|
||||
}
|
||||
populatedOptions = {
|
||||
hashAlgorithm: options.hash.algorithm,
|
||||
cpuMemCost: cpuMemCost,
|
||||
parallelization: parallelization,
|
||||
blockSize: blockSize,
|
||||
dkLen: dkLen,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, "Unsupported hash algorithm provider \"" + options.hash.algorithm + "\".");
|
||||
}
|
||||
return populatedOptions;
|
||||
};
|
||||
/**
|
||||
* Validates and returns the users list of the uploadAccount request.
|
||||
* Whenever a user with an error is detected, the error is cached and will later be
|
||||
* merged into the user import result. This allows the processing of valid users without
|
||||
* failing early on the first error detected.
|
||||
* @param {UserImportRecord[]} users The UserImportRecords to convert to UnploadAccountUser
|
||||
* objects.
|
||||
* @param {ValidatorFunction=} userValidator The user validator function.
|
||||
* @return {UploadAccountUser[]} The populated uploadAccount users.
|
||||
*/
|
||||
UserImportBuilder.prototype.populateUsers = function (users, userValidator) {
|
||||
var _this = this;
|
||||
var populatedUsers = [];
|
||||
users.forEach(function (user, index) {
|
||||
try {
|
||||
var result = populateUploadAccountUser(user, userValidator);
|
||||
if (typeof result.passwordHash !== 'undefined') {
|
||||
_this.requiresHashOptions = true;
|
||||
}
|
||||
// Only users that pass client screening will be passed to backend for processing.
|
||||
populatedUsers.push(result);
|
||||
// Map user's index (the one to be sent to backend) to original developer provided array.
|
||||
_this.indexMap[populatedUsers.length - 1] = index;
|
||||
}
|
||||
catch (error) {
|
||||
// Save the client side error with respect to the developer provided array.
|
||||
_this.userImportResultErrors.push({
|
||||
index: index,
|
||||
error: error,
|
||||
});
|
||||
}
|
||||
});
|
||||
return populatedUsers;
|
||||
};
|
||||
return UserImportBuilder;
|
||||
}());
|
||||
exports.UserImportBuilder = UserImportBuilder;
|
174
express-server/node_modules/firebase-admin/lib/auth/user-record.js
generated
vendored
Normal file
174
express-server/node_modules/firebase-admin/lib/auth/user-record.js
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/*! firebase-admin v6.4.0 */
|
||||
"use strict";
|
||||
/*!
|
||||
* Copyright 2017 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 deep_copy_1 = require("../utils/deep-copy");
|
||||
var utils = require("../utils");
|
||||
var error_1 = require("../utils/error");
|
||||
/**
|
||||
* Parses a time stamp string or number and returns the corresponding date if valid.
|
||||
*
|
||||
* @param {any} time The unix timestamp string or number in milliseconds.
|
||||
* @return {string} The corresponding date as a UTC string, if valid.
|
||||
*/
|
||||
function parseDate(time) {
|
||||
try {
|
||||
var date = new Date(parseInt(time, 10));
|
||||
if (!isNaN(date.getTime())) {
|
||||
return date.toUTCString();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Do nothing. null will be returned.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* User metadata class that provides metadata information like user account creation
|
||||
* and last sign in time.
|
||||
*
|
||||
* @param {object} response The server side response returned from the getAccountInfo
|
||||
* endpoint.
|
||||
* @constructor
|
||||
*/
|
||||
var UserMetadata = /** @class */ (function () {
|
||||
function UserMetadata(response) {
|
||||
// Creation date should always be available but due to some backend bugs there
|
||||
// were cases in the past where users did not have creation date properly set.
|
||||
// This included legacy Firebase migrating project users and some anonymous users.
|
||||
// These bugs have already been addressed since then.
|
||||
utils.addReadonlyGetter(this, 'creationTime', parseDate(response.createdAt));
|
||||
utils.addReadonlyGetter(this, 'lastSignInTime', parseDate(response.lastLoginAt));
|
||||
}
|
||||
/** @return {object} The plain object representation of the user's metadata. */
|
||||
UserMetadata.prototype.toJSON = function () {
|
||||
return {
|
||||
lastSignInTime: this.lastSignInTime,
|
||||
creationTime: this.creationTime,
|
||||
};
|
||||
};
|
||||
return UserMetadata;
|
||||
}());
|
||||
exports.UserMetadata = UserMetadata;
|
||||
/**
|
||||
* User info class that provides provider user information for different
|
||||
* Firebase providers like google.com, facebook.com, password, etc.
|
||||
*
|
||||
* @param {object} response The server side response returned from the getAccountInfo
|
||||
* endpoint.
|
||||
* @constructor
|
||||
*/
|
||||
var UserInfo = /** @class */ (function () {
|
||||
function UserInfo(response) {
|
||||
// Provider user id and provider id are required.
|
||||
if (!response.rawId || !response.providerId) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user info response');
|
||||
}
|
||||
utils.addReadonlyGetter(this, 'uid', response.rawId);
|
||||
utils.addReadonlyGetter(this, 'displayName', response.displayName);
|
||||
utils.addReadonlyGetter(this, 'email', response.email);
|
||||
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
|
||||
utils.addReadonlyGetter(this, 'providerId', response.providerId);
|
||||
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
|
||||
}
|
||||
/** @return {object} The plain object representation of the current provider data. */
|
||||
UserInfo.prototype.toJSON = function () {
|
||||
return {
|
||||
uid: this.uid,
|
||||
displayName: this.displayName,
|
||||
email: this.email,
|
||||
photoURL: this.photoURL,
|
||||
providerId: this.providerId,
|
||||
phoneNumber: this.phoneNumber,
|
||||
};
|
||||
};
|
||||
return UserInfo;
|
||||
}());
|
||||
exports.UserInfo = UserInfo;
|
||||
/**
|
||||
* User record class that defines the Firebase user object populated from
|
||||
* the Firebase Auth getAccountInfo response.
|
||||
*
|
||||
* @param {any} response The server side response returned from the getAccountInfo
|
||||
* endpoint.
|
||||
* @constructor
|
||||
*/
|
||||
var UserRecord = /** @class */ (function () {
|
||||
function UserRecord(response) {
|
||||
// The Firebase user id is required.
|
||||
if (!response.localId) {
|
||||
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user response');
|
||||
}
|
||||
utils.addReadonlyGetter(this, 'uid', response.localId);
|
||||
utils.addReadonlyGetter(this, 'email', response.email);
|
||||
utils.addReadonlyGetter(this, 'emailVerified', !!response.emailVerified);
|
||||
utils.addReadonlyGetter(this, 'displayName', response.displayName);
|
||||
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
|
||||
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
|
||||
// If disabled is not provided, the account is enabled by default.
|
||||
utils.addReadonlyGetter(this, 'disabled', response.disabled || false);
|
||||
utils.addReadonlyGetter(this, 'metadata', new UserMetadata(response));
|
||||
var providerData = [];
|
||||
for (var _i = 0, _a = (response.providerUserInfo || []); _i < _a.length; _i++) {
|
||||
var entry = _a[_i];
|
||||
providerData.push(new UserInfo(entry));
|
||||
}
|
||||
utils.addReadonlyGetter(this, 'providerData', providerData);
|
||||
utils.addReadonlyGetter(this, 'passwordHash', response.passwordHash);
|
||||
utils.addReadonlyGetter(this, 'passwordSalt', response.salt);
|
||||
try {
|
||||
utils.addReadonlyGetter(this, 'customClaims', JSON.parse(response.customAttributes));
|
||||
}
|
||||
catch (e) {
|
||||
// Ignore error.
|
||||
utils.addReadonlyGetter(this, 'customClaims', undefined);
|
||||
}
|
||||
var validAfterTime = null;
|
||||
// Convert validSince first to UTC milliseconds and then to UTC date string.
|
||||
if (typeof response.validSince !== 'undefined') {
|
||||
validAfterTime = parseDate(response.validSince * 1000);
|
||||
}
|
||||
utils.addReadonlyGetter(this, 'tokensValidAfterTime', validAfterTime);
|
||||
}
|
||||
/** @return {object} The plain object representation of the user record. */
|
||||
UserRecord.prototype.toJSON = function () {
|
||||
var json = {
|
||||
uid: this.uid,
|
||||
email: this.email,
|
||||
emailVerified: this.emailVerified,
|
||||
displayName: this.displayName,
|
||||
photoURL: this.photoURL,
|
||||
phoneNumber: this.phoneNumber,
|
||||
disabled: this.disabled,
|
||||
// Convert metadata to json.
|
||||
metadata: this.metadata.toJSON(),
|
||||
passwordHash: this.passwordHash,
|
||||
passwordSalt: this.passwordSalt,
|
||||
customClaims: deep_copy_1.deepCopy(this.customClaims),
|
||||
tokensValidAfterTime: this.tokensValidAfterTime,
|
||||
};
|
||||
json.providerData = [];
|
||||
for (var _i = 0, _a = this.providerData; _i < _a.length; _i++) {
|
||||
var entry = _a[_i];
|
||||
// Convert each provider data to json.
|
||||
json.providerData.push(entry.toJSON());
|
||||
}
|
||||
return json;
|
||||
};
|
||||
return UserRecord;
|
||||
}());
|
||||
exports.UserRecord = UserRecord;
|
Reference in New Issue
Block a user