mirror of
https://github.com/musix-org/musix-oss
synced 2024-12-24 11:13:18 +00:00
1504 lines
74 KiB
JavaScript
1504 lines
74 KiB
JavaScript
|
/*! firebase-admin v8.9.2 */
|
||
|
"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 = function (d, b) {
|
||
|
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 extendStatics(d, b);
|
||
|
};
|
||
|
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 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");
|
||
|
var auth_config_1 = require("./auth-config");
|
||
|
var tenant_1 = require("./tenant");
|
||
|
/** Firebase Auth request header. */
|
||
|
var FIREBASE_AUTH_HEADER = {
|
||
|
'X-Client-Version': 'Node/Admin/8.9.2',
|
||
|
};
|
||
|
/** 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;
|
||
|
/** Maximum allowed number of provider configurations to batch download at one time. */
|
||
|
var MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE = 100;
|
||
|
/** The Firebase Auth backend base URL format. */
|
||
|
var FIREBASE_AUTH_BASE_URL_FORMAT = 'https://identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
|
||
|
/** The Firebase Auth backend multi-tenancy base URL format. */
|
||
|
var FIREBASE_AUTH_TENANT_URL_FORMAT = FIREBASE_AUTH_BASE_URL_FORMAT.replace('projects/{projectId}', 'projects/{projectId}/tenants/{tenantId}');
|
||
|
/** Maximum allowed number of tenants to download at one time. */
|
||
|
var MAX_LIST_TENANT_PAGE_SIZE = 1000;
|
||
|
/** 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(app, version) {
|
||
|
if (version === void 0) { version = 'v1'; }
|
||
|
this.app = app;
|
||
|
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 {Promise<string>} The corresponding resource URL.
|
||
|
*/
|
||
|
AuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
|
||
|
var _this = this;
|
||
|
return this.getProjectId()
|
||
|
.then(function (projectId) {
|
||
|
var baseParams = {
|
||
|
version: _this.version,
|
||
|
projectId: projectId,
|
||
|
api: api || '',
|
||
|
};
|
||
|
var baseUrl = utils.formatString(_this.urlFormat, baseParams);
|
||
|
// Substitute additional api related parameters.
|
||
|
return utils.formatString(baseUrl, params || {});
|
||
|
});
|
||
|
};
|
||
|
AuthResourceUrlBuilder.prototype.getProjectId = function () {
|
||
|
var _this = this;
|
||
|
if (this.projectId) {
|
||
|
return Promise.resolve(this.projectId);
|
||
|
}
|
||
|
return utils.findProjectId(this.app)
|
||
|
.then(function (projectId) {
|
||
|
if (!validator.isNonEmptyString(projectId)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'Failed to determine project ID for Auth. Initialize the '
|
||
|
+ 'SDK with service account credentials or set project ID as an app option. '
|
||
|
+ 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.');
|
||
|
}
|
||
|
_this.projectId = projectId;
|
||
|
return projectId;
|
||
|
});
|
||
|
};
|
||
|
return AuthResourceUrlBuilder;
|
||
|
}());
|
||
|
/** Tenant aware resource builder utility. */
|
||
|
var TenantAwareAuthResourceUrlBuilder = /** @class */ (function (_super) {
|
||
|
__extends(TenantAwareAuthResourceUrlBuilder, _super);
|
||
|
/**
|
||
|
* The tenant aware resource URL builder constructor.
|
||
|
*
|
||
|
* @param {string} projectId The resource project ID.
|
||
|
* @param {string} version The endpoint API version.
|
||
|
* @param {string} tenantId The tenant ID.
|
||
|
* @constructor
|
||
|
*/
|
||
|
function TenantAwareAuthResourceUrlBuilder(app, version, tenantId) {
|
||
|
var _this = _super.call(this, app, version) || this;
|
||
|
_this.app = app;
|
||
|
_this.version = version;
|
||
|
_this.tenantId = tenantId;
|
||
|
_this.urlFormat = FIREBASE_AUTH_TENANT_URL_FORMAT;
|
||
|
return _this;
|
||
|
}
|
||
|
/**
|
||
|
* 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 {Promise<string>} The corresponding resource URL.
|
||
|
*/
|
||
|
TenantAwareAuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
|
||
|
var _this = this;
|
||
|
return _super.prototype.getUrl.call(this, api, params)
|
||
|
.then(function (url) {
|
||
|
return utils.formatString(url, { tenantId: _this.tenantId });
|
||
|
});
|
||
|
};
|
||
|
return TenantAwareAuthResourceUrlBuilder;
|
||
|
}(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,
|
||
|
// Pass tenantId only for uploadAccount requests.
|
||
|
tenantId: uploadAccountRequest,
|
||
|
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];
|
||
|
}
|
||
|
}
|
||
|
if (typeof request.tenantId !== 'undefined' &&
|
||
|
!validator.isNonEmptyString(request.tenantId)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID);
|
||
|
}
|
||
|
// 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 integer that does not exceed " +
|
||
|
(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');
|
||
|
}
|
||
|
// Throw error when tenantId is passed in POST body.
|
||
|
if (typeof request.tenantId !== 'undefined') {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "UpdateRequest" property.');
|
||
|
}
|
||
|
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.");
|
||
|
}
|
||
|
// Throw error when tenantId is passed in POST body.
|
||
|
if (typeof request.tenantId !== 'undefined') {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "CreateRequest" property.');
|
||
|
}
|
||
|
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');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the retrieve OIDC configuration endpoint settings. */
|
||
|
var GET_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'GET')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the OIDC provider resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get OIDC configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the delete OIDC configuration endpoint settings. */
|
||
|
var DELETE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'DELETE');
|
||
|
/** Instantiates the create OIDC configuration endpoint settings. */
|
||
|
var CREATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs?oauthIdpConfigId={providerId}', 'POST')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the OIDC provider resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the update OIDC configuration endpoint settings. */
|
||
|
var UPDATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the configuration resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the list OIDC configuration endpoint settings. */
|
||
|
var LIST_OAUTH_IDP_CONFIGS = new api_request_1.ApiSettings('/oauthIdpConfigs', 'GET')
|
||
|
// Set request validator.
|
||
|
.setRequestValidator(function (request) {
|
||
|
// Validate next page token.
|
||
|
if (typeof request.pageToken !== 'undefined' &&
|
||
|
!validator.isNonEmptyString(request.pageToken)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
||
|
}
|
||
|
// Validate max results.
|
||
|
if (!validator.isNumber(request.pageSize) ||
|
||
|
request.pageSize <= 0 ||
|
||
|
request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive integer that does not exceed " +
|
||
|
(MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the retrieve SAML configuration endpoint settings. */
|
||
|
var GET_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'GET')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the SAML provider resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get SAML configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the delete SAML configuration endpoint settings. */
|
||
|
var DELETE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'DELETE');
|
||
|
/** Instantiates the create SAML configuration endpoint settings. */
|
||
|
var CREATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs?inboundSamlConfigId={providerId}', 'POST')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the SAML provider resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the update SAML configuration endpoint settings. */
|
||
|
var UPDATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain the configuration resource name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML configuration');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the list SAML configuration endpoint settings. */
|
||
|
var LIST_INBOUND_SAML_CONFIGS = new api_request_1.ApiSettings('/inboundSamlConfigs', 'GET')
|
||
|
// Set request validator.
|
||
|
.setRequestValidator(function (request) {
|
||
|
// Validate next page token.
|
||
|
if (typeof request.pageToken !== 'undefined' &&
|
||
|
!validator.isNonEmptyString(request.pageToken)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
||
|
}
|
||
|
// Validate max results.
|
||
|
if (!validator.isNumber(request.pageSize) ||
|
||
|
request.pageSize <= 0 ||
|
||
|
request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive integer that does not exceed " +
|
||
|
(MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
|
||
|
}
|
||
|
});
|
||
|
/**
|
||
|
* Class that provides the mechanism to send requests to the Firebase Auth backend endpoints.
|
||
|
*/
|
||
|
var AbstractAuthRequestHandler = /** @class */ (function () {
|
||
|
/**
|
||
|
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
||
|
* @constructor
|
||
|
*/
|
||
|
function AbstractAuthRequestHandler(app) {
|
||
|
this.app = 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.');
|
||
|
}
|
||
|
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
|
||
|
}
|
||
|
/**
|
||
|
* @param {any} response The response to check for errors.
|
||
|
* @return {string|null} The error code if present; null otherwise.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.createSessionCookie = function (idToken, expiresIn) {
|
||
|
var request = {
|
||
|
idToken: idToken,
|
||
|
// Convert to seconds.
|
||
|
validDuration: expiresIn / 1000,
|
||
|
};
|
||
|
return this.invokeRequestHandler(this.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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 || request.users.length === 0) {
|
||
|
return Promise.resolve(userImportBuilder.buildResponse([]));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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.getAuthUrlBuilder(), 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. Required when requestType == 'EMAIL_SIGNIN'
|
||
|
* @return {Promise<string>} A promise that resolves with the email action link.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.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') {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "`actionCodeSettings` is required when `requestType` === 'EMAIL_SIGNIN'"));
|
||
|
}
|
||
|
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.getAuthUrlBuilder(), FIREBASE_AUTH_GET_OOB_CODE, request)
|
||
|
.then(function (response) {
|
||
|
// Return the link.
|
||
|
return response.oobLink;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Looks up an OIDC provider configuration by provider ID.
|
||
|
*
|
||
|
* @param {string} providerId The provider identifier of the configuration to lookup.
|
||
|
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the provider configuration information.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.getOAuthIdpConfig = function (providerId) {
|
||
|
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_OAUTH_IDP_CONFIG, {}, { providerId: providerId });
|
||
|
};
|
||
|
/**
|
||
|
* Lists the OIDC configurations (single batch only) with a size of maxResults and starting from
|
||
|
* the offset as specified by pageToken.
|
||
|
*
|
||
|
* @param {number=} maxResults The page size, 100 if undefined. This is also the maximum
|
||
|
* allowed limit.
|
||
|
* @param {string=} pageToken The next page token. If not specified, returns OIDC configurations
|
||
|
* without any offset. Configurations 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
|
||
|
* OIDC configurations and the next page token if available. For the last page, an empty list of provider
|
||
|
* configuration and no page token are returned.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.listOAuthIdpConfigs = function (maxResults, pageToken) {
|
||
|
if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
|
||
|
var request = {
|
||
|
pageSize: maxResults,
|
||
|
};
|
||
|
// Add next page token if provided.
|
||
|
if (typeof pageToken !== 'undefined') {
|
||
|
request.pageToken = pageToken;
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_OAUTH_IDP_CONFIGS, request)
|
||
|
.then(function (response) {
|
||
|
if (!response.oauthIdpConfigs) {
|
||
|
response.oauthIdpConfigs = [];
|
||
|
delete response.nextPageToken;
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Deletes an OIDC configuration identified by a providerId.
|
||
|
*
|
||
|
* @param {string} providerId The identifier of the OIDC configuration to delete.
|
||
|
* @return {Promise<void>} A promise that resolves when the OIDC provider is deleted.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.deleteOAuthIdpConfig = function (providerId) {
|
||
|
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_OAUTH_IDP_CONFIG, {}, { providerId: providerId })
|
||
|
.then(function (response) {
|
||
|
// Return nothing.
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Creates a new OIDC provider configuration with the properties provided.
|
||
|
*
|
||
|
* @param {AuthProviderConfig} options The properties to set on the new OIDC provider configuration to be created.
|
||
|
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the newly created OIDC
|
||
|
* configuration.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.createOAuthIdpConfig = function (options) {
|
||
|
// Construct backend request.
|
||
|
var request;
|
||
|
try {
|
||
|
request = auth_config_1.OIDCConfig.buildServerRequest(options) || {};
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
var providerId = options.providerId;
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_OAUTH_IDP_CONFIG, request, { providerId: providerId })
|
||
|
.then(function (response) {
|
||
|
if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC provider configuration');
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Updates an existing OIDC provider configuration with the properties provided.
|
||
|
*
|
||
|
* @param {string} providerId The provider identifier of the OIDC configuration to update.
|
||
|
* @param {OIDCUpdateAuthProviderRequest} options The properties to update on the existing configuration.
|
||
|
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the modified provider
|
||
|
* configuration.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.updateOAuthIdpConfig = function (providerId, options) {
|
||
|
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
// Construct backend request.
|
||
|
var request;
|
||
|
try {
|
||
|
request = auth_config_1.OIDCConfig.buildServerRequest(options, true) || {};
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
var updateMask = utils.generateUpdateMask(request);
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_OAUTH_IDP_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
|
||
|
.then(function (response) {
|
||
|
if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC provider configuration');
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Looks up an SAML provider configuration by provider ID.
|
||
|
*
|
||
|
* @param {string} providerId The provider identifier of the configuration to lookup.
|
||
|
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the provider configuration information.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.getInboundSamlConfig = function (providerId) {
|
||
|
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_INBOUND_SAML_CONFIG, {}, { providerId: providerId });
|
||
|
};
|
||
|
/**
|
||
|
* Lists the SAML configurations (single batch only) with a size of maxResults and starting from
|
||
|
* the offset as specified by pageToken.
|
||
|
*
|
||
|
* @param {number=} maxResults The page size, 100 if undefined. This is also the maximum
|
||
|
* allowed limit.
|
||
|
* @param {string=} pageToken The next page token. If not specified, returns SAML configurations starting
|
||
|
* without any offset. Configurations 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
|
||
|
* SAML configurations and the next page token if available. For the last page, an empty list of provider
|
||
|
* configuration and no page token are returned.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.listInboundSamlConfigs = function (maxResults, pageToken) {
|
||
|
if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
|
||
|
var request = {
|
||
|
pageSize: maxResults,
|
||
|
};
|
||
|
// Add next page token if provided.
|
||
|
if (typeof pageToken !== 'undefined') {
|
||
|
request.pageToken = pageToken;
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_INBOUND_SAML_CONFIGS, request)
|
||
|
.then(function (response) {
|
||
|
if (!response.inboundSamlConfigs) {
|
||
|
response.inboundSamlConfigs = [];
|
||
|
delete response.nextPageToken;
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Deletes a SAML configuration identified by a providerId.
|
||
|
*
|
||
|
* @param {string} providerId The identifier of the SAML configuration to delete.
|
||
|
* @return {Promise<void>} A promise that resolves when the SAML provider is deleted.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.deleteInboundSamlConfig = function (providerId) {
|
||
|
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_INBOUND_SAML_CONFIG, {}, { providerId: providerId })
|
||
|
.then(function (response) {
|
||
|
// Return nothing.
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Creates a new SAML provider configuration with the properties provided.
|
||
|
*
|
||
|
* @param {AuthProviderConfig} options The properties to set on the new SAML provider configuration to be created.
|
||
|
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the newly created SAML
|
||
|
* configuration.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.createInboundSamlConfig = function (options) {
|
||
|
// Construct backend request.
|
||
|
var request;
|
||
|
try {
|
||
|
request = auth_config_1.SAMLConfig.buildServerRequest(options) || {};
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
var providerId = options.providerId;
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_INBOUND_SAML_CONFIG, request, { providerId: providerId })
|
||
|
.then(function (response) {
|
||
|
if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML provider configuration');
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Updates an existing SAML provider configuration with the properties provided.
|
||
|
*
|
||
|
* @param {string} providerId The provider identifier of the SAML configuration to update.
|
||
|
* @param {SAMLUpdateAuthProviderRequest} options The properties to update on the existing configuration.
|
||
|
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the modified provider
|
||
|
* configuration.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.updateInboundSamlConfig = function (providerId, options) {
|
||
|
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
||
|
}
|
||
|
// Construct backend request.
|
||
|
var request;
|
||
|
try {
|
||
|
request = auth_config_1.SAMLConfig.buildServerRequest(options, true) || {};
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
var updateMask = utils.generateUpdateMask(request);
|
||
|
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_INBOUND_SAML_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
|
||
|
.then(function (response) {
|
||
|
if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML provider configuration');
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* 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.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.invokeRequestHandler = function (urlBuilder, apiSettings, requestData, additionalResourceParams) {
|
||
|
var _this = this;
|
||
|
return urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams)
|
||
|
.then(function (url) {
|
||
|
// Validate request.
|
||
|
var requestValidator = apiSettings.getRequestValidator();
|
||
|
requestValidator(requestData);
|
||
|
// Process request.
|
||
|
var req = {
|
||
|
method: apiSettings.getHttpMethod(),
|
||
|
url: url,
|
||
|
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 = AbstractAuthRequestHandler.getErrorCode(error);
|
||
|
if (!errorCode) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Error returned from server: ' + error + '. Additionally, an ' +
|
||
|
'internal error occurred while attempting to extract the ' +
|
||
|
'errorcode from the error.');
|
||
|
}
|
||
|
throw error_1.FirebaseAuthError.fromServerError(errorCode, /* message */ undefined, error);
|
||
|
}
|
||
|
throw err;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} The current Auth user management resource URL builder.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.getAuthUrlBuilder = function () {
|
||
|
if (!this.authUrlBuilder) {
|
||
|
this.authUrlBuilder = this.newAuthUrlBuilder();
|
||
|
}
|
||
|
return this.authUrlBuilder;
|
||
|
};
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} The current project config resource URL builder.
|
||
|
*/
|
||
|
AbstractAuthRequestHandler.prototype.getProjectConfigUrlBuilder = function () {
|
||
|
if (!this.projectConfigUrlBuilder) {
|
||
|
this.projectConfigUrlBuilder = this.newProjectConfigUrlBuilder();
|
||
|
}
|
||
|
return this.projectConfigUrlBuilder;
|
||
|
};
|
||
|
return AbstractAuthRequestHandler;
|
||
|
}());
|
||
|
exports.AbstractAuthRequestHandler = AbstractAuthRequestHandler;
|
||
|
/** Instantiates the getTenant endpoint settings. */
|
||
|
var GET_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'GET')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain at least the tenant name.
|
||
|
if (!validator.isNonEmptyString(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get tenant');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the deleteTenant endpoint settings. */
|
||
|
var DELETE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'DELETE');
|
||
|
/** Instantiates the updateTenant endpoint settings. */
|
||
|
var UPDATE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}?updateMask={updateMask}', 'PATCH')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain at least the tenant name.
|
||
|
if (!validator.isNonEmptyString(response.name) ||
|
||
|
!tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update tenant');
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the listTenants endpoint settings. */
|
||
|
var LIST_TENANTS = new api_request_1.ApiSettings('/tenants', 'GET')
|
||
|
// Set request validator.
|
||
|
.setRequestValidator(function (request) {
|
||
|
// Validate next page token.
|
||
|
if (typeof request.pageToken !== 'undefined' &&
|
||
|
!validator.isNonEmptyString(request.pageToken)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
||
|
}
|
||
|
// Validate max results.
|
||
|
if (!validator.isNumber(request.pageSize) ||
|
||
|
request.pageSize <= 0 ||
|
||
|
request.pageSize > MAX_LIST_TENANT_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_LIST_TENANT_PAGE_SIZE + "."));
|
||
|
}
|
||
|
});
|
||
|
/** Instantiates the createTenant endpoint settings. */
|
||
|
var CREATE_TENANT = new api_request_1.ApiSettings('/tenants', 'POST')
|
||
|
// Set response validator.
|
||
|
.setResponseValidator(function (response) {
|
||
|
// Response should always contain at least the tenant name.
|
||
|
if (!validator.isNonEmptyString(response.name) ||
|
||
|
!tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new tenant');
|
||
|
}
|
||
|
});
|
||
|
/**
|
||
|
* Utility for sending requests to Auth server that are Auth instance related. This includes user and
|
||
|
* tenant management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
|
||
|
* additional tenant management related APIs.
|
||
|
*/
|
||
|
var AuthRequestHandler = /** @class */ (function (_super) {
|
||
|
__extends(AuthRequestHandler, _super);
|
||
|
/**
|
||
|
* The FirebaseAuthRequestHandler constructor used to initialize an instance using a FirebaseApp.
|
||
|
*
|
||
|
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
||
|
* @constructor.
|
||
|
*/
|
||
|
function AuthRequestHandler(app) {
|
||
|
var _this = _super.call(this, app) || this;
|
||
|
_this.tenantMgmtResourceBuilder = new AuthResourceUrlBuilder(app, 'v2');
|
||
|
return _this;
|
||
|
}
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} A new Auth user management resource URL builder instance.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.newAuthUrlBuilder = function () {
|
||
|
return new AuthResourceUrlBuilder(this.app, 'v1');
|
||
|
};
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} A new project config resource URL builder instance.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
|
||
|
return new AuthResourceUrlBuilder(this.app, 'v2');
|
||
|
};
|
||
|
/**
|
||
|
* Looks up a tenant by tenant ID.
|
||
|
*
|
||
|
* @param {string} tenantId The tenant identifier of the tenant to lookup.
|
||
|
* @return {Promise<TenantServerResponse>} A promise that resolves with the tenant information.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.getTenant = function (tenantId) {
|
||
|
if (!validator.isNonEmptyString(tenantId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, GET_TENANT, {}, { tenantId: tenantId })
|
||
|
.then(function (response) {
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Exports the tenants (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 tenants starting
|
||
|
* without any offset. Tenants 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
|
||
|
* tenants and the next page token if available. For the last page, an empty list of tenants
|
||
|
* and no page token are returned.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.listTenants = function (maxResults, pageToken) {
|
||
|
if (maxResults === void 0) { maxResults = MAX_LIST_TENANT_PAGE_SIZE; }
|
||
|
var request = {
|
||
|
pageSize: maxResults,
|
||
|
pageToken: pageToken,
|
||
|
};
|
||
|
// Remove next page token if not provided.
|
||
|
if (typeof request.pageToken === 'undefined') {
|
||
|
delete request.pageToken;
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, LIST_TENANTS, request)
|
||
|
.then(function (response) {
|
||
|
if (!response.tenants) {
|
||
|
response.tenants = [];
|
||
|
delete response.nextPageToken;
|
||
|
}
|
||
|
return response;
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Deletes a tenant identified by a tenantId.
|
||
|
*
|
||
|
* @param {string} tenantId The identifier of the tenant to delete.
|
||
|
* @return {Promise<void>} A promise that resolves when the tenant is deleted.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.deleteTenant = function (tenantId) {
|
||
|
if (!validator.isNonEmptyString(tenantId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
||
|
}
|
||
|
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, DELETE_TENANT, {}, { tenantId: tenantId })
|
||
|
.then(function (response) {
|
||
|
// Return nothing.
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Creates a new tenant with the properties provided.
|
||
|
*
|
||
|
* @param {TenantOptions} tenantOptions The properties to set on the new tenant to be created.
|
||
|
* @return {Promise<TenantServerResponse>} A promise that resolves with the newly created tenant object.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.createTenant = function (tenantOptions) {
|
||
|
try {
|
||
|
// Construct backend request.
|
||
|
var request = tenant_1.Tenant.buildServerRequest(tenantOptions, true);
|
||
|
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, CREATE_TENANT, request)
|
||
|
.then(function (response) {
|
||
|
return response;
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
};
|
||
|
/**
|
||
|
* Updates an existing tenant with the properties provided.
|
||
|
*
|
||
|
* @param {string} tenantId The tenant identifier of the tenant to update.
|
||
|
* @param {TenantOptions} tenantOptions The properties to update on the existing tenant.
|
||
|
* @return {Promise<TenantServerResponse>} A promise that resolves with the modified tenant object.
|
||
|
*/
|
||
|
AuthRequestHandler.prototype.updateTenant = function (tenantId, tenantOptions) {
|
||
|
if (!validator.isNonEmptyString(tenantId)) {
|
||
|
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
||
|
}
|
||
|
try {
|
||
|
// Construct backend request.
|
||
|
var request = tenant_1.Tenant.buildServerRequest(tenantOptions, false);
|
||
|
var updateMask = utils.generateUpdateMask(request);
|
||
|
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, UPDATE_TENANT, request, { tenantId: tenantId, updateMask: updateMask.join(',') })
|
||
|
.then(function (response) {
|
||
|
return response;
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
return Promise.reject(e);
|
||
|
}
|
||
|
};
|
||
|
return AuthRequestHandler;
|
||
|
}(AbstractAuthRequestHandler));
|
||
|
exports.AuthRequestHandler = AuthRequestHandler;
|
||
|
/**
|
||
|
* Utility for sending requests to Auth server that are tenant Auth instance related. This includes user
|
||
|
* management related APIs for specified tenants.
|
||
|
* This extends the BaseFirebaseAuthRequestHandler class.
|
||
|
*/
|
||
|
var TenantAwareAuthRequestHandler = /** @class */ (function (_super) {
|
||
|
__extends(TenantAwareAuthRequestHandler, _super);
|
||
|
/**
|
||
|
* The FirebaseTenantRequestHandler constructor used to initialize an instance using a
|
||
|
* FirebaseApp and a tenant ID.
|
||
|
*
|
||
|
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
||
|
* @param {string} tenantId The request handler's tenant ID.
|
||
|
* @constructor
|
||
|
*/
|
||
|
function TenantAwareAuthRequestHandler(app, tenantId) {
|
||
|
var _this = _super.call(this, app) || this;
|
||
|
_this.tenantId = tenantId;
|
||
|
return _this;
|
||
|
}
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} A new Auth user management resource URL builder instance.
|
||
|
*/
|
||
|
TenantAwareAuthRequestHandler.prototype.newAuthUrlBuilder = function () {
|
||
|
return new TenantAwareAuthResourceUrlBuilder(this.app, 'v1', this.tenantId);
|
||
|
};
|
||
|
/**
|
||
|
* @return {AuthResourceUrlBuilder} A new project config resource URL builder instance.
|
||
|
*/
|
||
|
TenantAwareAuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
|
||
|
return new TenantAwareAuthResourceUrlBuilder(this.app, 'v2', this.tenantId);
|
||
|
};
|
||
|
/**
|
||
|
* 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.
|
||
|
*
|
||
|
* Overrides the superclass methods by adding an additional check to match tenant IDs of
|
||
|
* imported user records if present.
|
||
|
*
|
||
|
* @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.
|
||
|
*/
|
||
|
TenantAwareAuthRequestHandler.prototype.uploadAccount = function (users, options) {
|
||
|
var _this = this;
|
||
|
// Add additional check to match tenant ID of imported user records.
|
||
|
users.forEach(function (user, index) {
|
||
|
if (validator.isNonEmptyString(user.tenantId) &&
|
||
|
user.tenantId !== _this.tenantId) {
|
||
|
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISMATCHING_TENANT_ID, "UserRecord of index \"" + index + "\" has mismatching tenant ID \"" + user.tenantId + "\"");
|
||
|
}
|
||
|
});
|
||
|
return _super.prototype.uploadAccount.call(this, users, options);
|
||
|
};
|
||
|
return TenantAwareAuthRequestHandler;
|
||
|
}(AbstractAuthRequestHandler));
|
||
|
exports.TenantAwareAuthRequestHandler = TenantAwareAuthRequestHandler;
|