UNPKG

92.7 kBJavaScriptView Raw
1/*! firebase-admin v10.0.0 */
2"use strict";
3/*!
4 * @license
5 * Copyright 2017 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19var __extends = (this && this.__extends) || (function () {
20 var extendStatics = function (d, b) {
21 extendStatics = Object.setPrototypeOf ||
22 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
23 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
24 return extendStatics(d, b);
25 };
26 return function (d, b) {
27 extendStatics(d, b);
28 function __() { this.constructor = d; }
29 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
30 };
31})();
32Object.defineProperty(exports, "__esModule", { value: true });
33exports.useEmulator = exports.TenantAwareAuthRequestHandler = exports.AuthRequestHandler = exports.AbstractAuthRequestHandler = exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = exports.FIREBASE_AUTH_SET_ACCOUNT_INFO = exports.FIREBASE_AUTH_BATCH_DELETE_ACCOUNTS = exports.FIREBASE_AUTH_DELETE_ACCOUNT = exports.FIREBASE_AUTH_GET_ACCOUNTS_INFO = exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = exports.FIREBASE_AUTH_UPLOAD_ACCOUNT = exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE = exports.EMAIL_ACTION_REQUEST_TYPES = exports.RESERVED_CLAIMS = void 0;
34var validator = require("../utils/validator");
35var deep_copy_1 = require("../utils/deep-copy");
36var error_1 = require("../utils/error");
37var api_request_1 = require("../utils/api-request");
38var utils = require("../utils/index");
39var user_import_builder_1 = require("./user-import-builder");
40var action_code_settings_builder_1 = require("./action-code-settings-builder");
41var tenant_1 = require("./tenant");
42var identifier_1 = require("./identifier");
43var auth_config_1 = require("./auth-config");
44/** Firebase Auth request header. */
45var FIREBASE_AUTH_HEADER = {
46 'X-Client-Version': "Node/Admin/" + utils.getSdkVersion(),
47};
48/** Firebase Auth request timeout duration in milliseconds. */
49var FIREBASE_AUTH_TIMEOUT = 25000;
50/** List of reserved claims which cannot be provided when creating a custom token. */
51exports.RESERVED_CLAIMS = [
52 'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat',
53 'iss', 'jti', 'nbf', 'nonce', 'sub', 'firebase',
54];
55/** List of supported email action request types. */
56exports.EMAIL_ACTION_REQUEST_TYPES = [
57 'PASSWORD_RESET', 'VERIFY_EMAIL', 'EMAIL_SIGNIN',
58];
59/** Maximum allowed number of characters in the custom claims payload. */
60var MAX_CLAIMS_PAYLOAD_SIZE = 1000;
61/** Maximum allowed number of users to batch download at one time. */
62var MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE = 1000;
63/** Maximum allowed number of users to batch upload at one time. */
64var MAX_UPLOAD_ACCOUNT_BATCH_SIZE = 1000;
65/** Maximum allowed number of users to batch get at one time. */
66var MAX_GET_ACCOUNTS_BATCH_SIZE = 100;
67/** Maximum allowed number of users to batch delete at one time. */
68var MAX_DELETE_ACCOUNTS_BATCH_SIZE = 1000;
69/** Minimum allowed session cookie duration in seconds (5 minutes). */
70var MIN_SESSION_COOKIE_DURATION_SECS = 5 * 60;
71/** Maximum allowed session cookie duration in seconds (2 weeks). */
72var MAX_SESSION_COOKIE_DURATION_SECS = 14 * 24 * 60 * 60;
73/** Maximum allowed number of provider configurations to batch download at one time. */
74var MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE = 100;
75/** The Firebase Auth backend base URL format. */
76var FIREBASE_AUTH_BASE_URL_FORMAT = 'https://identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
77/** Firebase Auth base URlLformat when using the auth emultor. */
78var FIREBASE_AUTH_EMULATOR_BASE_URL_FORMAT = 'http://{host}/identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
79/** The Firebase Auth backend multi-tenancy base URL format. */
80var FIREBASE_AUTH_TENANT_URL_FORMAT = FIREBASE_AUTH_BASE_URL_FORMAT.replace('projects/{projectId}', 'projects/{projectId}/tenants/{tenantId}');
81/** Firebase Auth base URL format when using the auth emultor with multi-tenancy. */
82var FIREBASE_AUTH_EMULATOR_TENANT_URL_FORMAT = FIREBASE_AUTH_EMULATOR_BASE_URL_FORMAT.replace('projects/{projectId}', 'projects/{projectId}/tenants/{tenantId}');
83/** Maximum allowed number of tenants to download at one time. */
84var MAX_LIST_TENANT_PAGE_SIZE = 1000;
85/**
86 * Enum for the user write operation type.
87 */
88var WriteOperationType;
89(function (WriteOperationType) {
90 WriteOperationType["Create"] = "create";
91 WriteOperationType["Update"] = "update";
92 WriteOperationType["Upload"] = "upload";
93})(WriteOperationType || (WriteOperationType = {}));
94/** Defines a base utility to help with resource URL construction. */
95var AuthResourceUrlBuilder = /** @class */ (function () {
96 /**
97 * The resource URL builder constructor.
98 *
99 * @param projectId - The resource project ID.
100 * @param version - The endpoint API version.
101 * @constructor
102 */
103 function AuthResourceUrlBuilder(app, version) {
104 if (version === void 0) { version = 'v1'; }
105 this.app = app;
106 this.version = version;
107 if (useEmulator()) {
108 this.urlFormat = utils.formatString(FIREBASE_AUTH_EMULATOR_BASE_URL_FORMAT, {
109 host: emulatorHost()
110 });
111 }
112 else {
113 this.urlFormat = FIREBASE_AUTH_BASE_URL_FORMAT;
114 }
115 }
116 /**
117 * Returns the resource URL corresponding to the provided parameters.
118 *
119 * @param api - The backend API name.
120 * @param params - The optional additional parameters to substitute in the
121 * URL path.
122 * @returns The corresponding resource URL.
123 */
124 AuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
125 var _this = this;
126 return this.getProjectId()
127 .then(function (projectId) {
128 var baseParams = {
129 version: _this.version,
130 projectId: projectId,
131 api: api || '',
132 };
133 var baseUrl = utils.formatString(_this.urlFormat, baseParams);
134 // Substitute additional api related parameters.
135 return utils.formatString(baseUrl, params || {});
136 });
137 };
138 AuthResourceUrlBuilder.prototype.getProjectId = function () {
139 var _this = this;
140 if (this.projectId) {
141 return Promise.resolve(this.projectId);
142 }
143 return utils.findProjectId(this.app)
144 .then(function (projectId) {
145 if (!validator.isNonEmptyString(projectId)) {
146 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'Failed to determine project ID for Auth. Initialize the '
147 + 'SDK with service account credentials or set project ID as an app option. '
148 + 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.');
149 }
150 _this.projectId = projectId;
151 return projectId;
152 });
153 };
154 return AuthResourceUrlBuilder;
155}());
156/** Tenant aware resource builder utility. */
157var TenantAwareAuthResourceUrlBuilder = /** @class */ (function (_super) {
158 __extends(TenantAwareAuthResourceUrlBuilder, _super);
159 /**
160 * The tenant aware resource URL builder constructor.
161 *
162 * @param projectId - The resource project ID.
163 * @param version - The endpoint API version.
164 * @param tenantId - The tenant ID.
165 * @constructor
166 */
167 function TenantAwareAuthResourceUrlBuilder(app, version, tenantId) {
168 var _this = _super.call(this, app, version) || this;
169 _this.app = app;
170 _this.version = version;
171 _this.tenantId = tenantId;
172 if (useEmulator()) {
173 _this.urlFormat = utils.formatString(FIREBASE_AUTH_EMULATOR_TENANT_URL_FORMAT, {
174 host: emulatorHost()
175 });
176 }
177 else {
178 _this.urlFormat = FIREBASE_AUTH_TENANT_URL_FORMAT;
179 }
180 return _this;
181 }
182 /**
183 * Returns the resource URL corresponding to the provided parameters.
184 *
185 * @param api - The backend API name.
186 * @param params - The optional additional parameters to substitute in the
187 * URL path.
188 * @returns The corresponding resource URL.
189 */
190 TenantAwareAuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
191 var _this = this;
192 return _super.prototype.getUrl.call(this, api, params)
193 .then(function (url) {
194 return utils.formatString(url, { tenantId: _this.tenantId });
195 });
196 };
197 return TenantAwareAuthResourceUrlBuilder;
198}(AuthResourceUrlBuilder));
199/**
200 * Auth-specific HTTP client which uses the special "owner" token
201 * when communicating with the Auth Emulator.
202 */
203var AuthHttpClient = /** @class */ (function (_super) {
204 __extends(AuthHttpClient, _super);
205 function AuthHttpClient() {
206 return _super !== null && _super.apply(this, arguments) || this;
207 }
208 AuthHttpClient.prototype.getToken = function () {
209 if (useEmulator()) {
210 return Promise.resolve('owner');
211 }
212 return _super.prototype.getToken.call(this);
213 };
214 return AuthHttpClient;
215}(api_request_1.AuthorizedHttpClient));
216/**
217 * Validates an AuthFactorInfo object. All unsupported parameters
218 * are removed from the original request. If an invalid field is passed
219 * an error is thrown.
220 *
221 * @param request - The AuthFactorInfo request object.
222 */
223function validateAuthFactorInfo(request) {
224 var validKeys = {
225 mfaEnrollmentId: true,
226 displayName: true,
227 phoneInfo: true,
228 enrolledAt: true,
229 };
230 // Remove unsupported keys from the original request.
231 for (var key in request) {
232 if (!(key in validKeys)) {
233 delete request[key];
234 }
235 }
236 // No enrollment ID is available for signupNewUser. Use another identifier.
237 var authFactorInfoIdentifier = request.mfaEnrollmentId || request.phoneInfo || JSON.stringify(request);
238 // Enrollment uid may or may not be specified for update operations.
239 if (typeof request.mfaEnrollmentId !== 'undefined' &&
240 !validator.isNonEmptyString(request.mfaEnrollmentId)) {
241 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, 'The second factor "uid" must be a valid non-empty string.');
242 }
243 if (typeof request.displayName !== 'undefined' &&
244 !validator.isString(request.displayName)) {
245 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME, "The second factor \"displayName\" for \"" + authFactorInfoIdentifier + "\" must be a valid string.");
246 }
247 // enrolledAt must be a valid UTC date string.
248 if (typeof request.enrolledAt !== 'undefined' &&
249 !validator.isISODateString(request.enrolledAt)) {
250 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLMENT_TIME, "The second factor \"enrollmentTime\" for \"" + authFactorInfoIdentifier + "\" must be a valid " +
251 'UTC date string.');
252 }
253 // Validate required fields depending on second factor type.
254 if (typeof request.phoneInfo !== 'undefined') {
255 // phoneNumber should be a string and a valid phone number.
256 if (!validator.isPhoneNumber(request.phoneInfo)) {
257 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER, "The second factor \"phoneNumber\" for \"" + authFactorInfoIdentifier + "\" must be a non-empty " +
258 'E.164 standard compliant identifier string.');
259 }
260 }
261 else {
262 // Invalid second factor. For example, a phone second factor may have been provided without
263 // a phone number. A TOTP based second factor may require a secret key, etc.
264 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLED_FACTORS, 'MFAInfo object provided is invalid.');
265 }
266}
267/**
268 * Validates a providerUserInfo object. All unsupported parameters
269 * are removed from the original request. If an invalid field is passed
270 * an error is thrown.
271 *
272 * @param request - The providerUserInfo request object.
273 */
274function validateProviderUserInfo(request) {
275 var validKeys = {
276 rawId: true,
277 providerId: true,
278 email: true,
279 displayName: true,
280 photoUrl: true,
281 };
282 // Remove invalid keys from original request.
283 for (var key in request) {
284 if (!(key in validKeys)) {
285 delete request[key];
286 }
287 }
288 if (!validator.isNonEmptyString(request.providerId)) {
289 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
290 }
291 if (typeof request.displayName !== 'undefined' &&
292 typeof request.displayName !== 'string') {
293 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME, "The provider \"displayName\" for \"" + request.providerId + "\" must be a valid string.");
294 }
295 if (!validator.isNonEmptyString(request.rawId)) {
296 // This is called localId on the backend but the developer specifies this as
297 // uid externally. So the error message should use the client facing name.
298 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, "The provider \"uid\" for \"" + request.providerId + "\" must be a valid non-empty string.");
299 }
300 // email should be a string and a valid email.
301 if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
302 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL, "The provider \"email\" for \"" + request.providerId + "\" must be a valid email string.");
303 }
304 // photoUrl should be a URL.
305 if (typeof request.photoUrl !== 'undefined' &&
306 !validator.isURL(request.photoUrl)) {
307 // This is called photoUrl on the backend but the developer specifies this as
308 // photoURL externally. So the error message should use the client facing name.
309 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL, "The provider \"photoURL\" for \"" + request.providerId + "\" must be a valid URL string.");
310 }
311}
312/**
313 * Validates a create/edit request object. All unsupported parameters
314 * are removed from the original request. If an invalid field is passed
315 * an error is thrown.
316 *
317 * @param request - The create/edit request object.
318 * @param writeOperationType - The write operation type.
319 */
320function validateCreateEditRequest(request, writeOperationType) {
321 var uploadAccountRequest = writeOperationType === WriteOperationType.Upload;
322 // Hash set of whitelisted parameters.
323 var validKeys = {
324 displayName: true,
325 localId: true,
326 email: true,
327 password: true,
328 rawPassword: true,
329 emailVerified: true,
330 photoUrl: true,
331 disabled: true,
332 disableUser: true,
333 deleteAttribute: true,
334 deleteProvider: true,
335 sanityCheck: true,
336 phoneNumber: true,
337 customAttributes: true,
338 validSince: true,
339 // Pass linkProviderUserInfo only for updates (i.e. not for uploads.)
340 linkProviderUserInfo: !uploadAccountRequest,
341 // Pass tenantId only for uploadAccount requests.
342 tenantId: uploadAccountRequest,
343 passwordHash: uploadAccountRequest,
344 salt: uploadAccountRequest,
345 createdAt: uploadAccountRequest,
346 lastLoginAt: uploadAccountRequest,
347 providerUserInfo: uploadAccountRequest,
348 mfaInfo: uploadAccountRequest,
349 // Only for non-uploadAccount requests.
350 mfa: !uploadAccountRequest,
351 };
352 // Remove invalid keys from original request.
353 for (var key in request) {
354 if (!(key in validKeys)) {
355 delete request[key];
356 }
357 }
358 if (typeof request.tenantId !== 'undefined' &&
359 !validator.isNonEmptyString(request.tenantId)) {
360 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID);
361 }
362 // For any invalid parameter, use the external key name in the error description.
363 // displayName should be a string.
364 if (typeof request.displayName !== 'undefined' &&
365 !validator.isString(request.displayName)) {
366 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME);
367 }
368 if ((typeof request.localId !== 'undefined' || uploadAccountRequest) &&
369 !validator.isUid(request.localId)) {
370 // This is called localId on the backend but the developer specifies this as
371 // uid externally. So the error message should use the client facing name.
372 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
373 }
374 // email should be a string and a valid email.
375 if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
376 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
377 }
378 // phoneNumber should be a string and a valid phone number.
379 if (typeof request.phoneNumber !== 'undefined' &&
380 !validator.isPhoneNumber(request.phoneNumber)) {
381 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER);
382 }
383 // password should be a string and a minimum of 6 chars.
384 if (typeof request.password !== 'undefined' &&
385 !validator.isPassword(request.password)) {
386 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
387 }
388 // rawPassword should be a string and a minimum of 6 chars.
389 if (typeof request.rawPassword !== 'undefined' &&
390 !validator.isPassword(request.rawPassword)) {
391 // This is called rawPassword on the backend but the developer specifies this as
392 // password externally. So the error message should use the client facing name.
393 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
394 }
395 // emailVerified should be a boolean.
396 if (typeof request.emailVerified !== 'undefined' &&
397 typeof request.emailVerified !== 'boolean') {
398 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL_VERIFIED);
399 }
400 // photoUrl should be a URL.
401 if (typeof request.photoUrl !== 'undefined' &&
402 !validator.isURL(request.photoUrl)) {
403 // This is called photoUrl on the backend but the developer specifies this as
404 // photoURL externally. So the error message should use the client facing name.
405 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL);
406 }
407 // disabled should be a boolean.
408 if (typeof request.disabled !== 'undefined' &&
409 typeof request.disabled !== 'boolean') {
410 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
411 }
412 // validSince should be a number.
413 if (typeof request.validSince !== 'undefined' &&
414 !validator.isNumber(request.validSince)) {
415 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TOKENS_VALID_AFTER_TIME);
416 }
417 // createdAt should be a number.
418 if (typeof request.createdAt !== 'undefined' &&
419 !validator.isNumber(request.createdAt)) {
420 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREATION_TIME);
421 }
422 // lastSignInAt should be a number.
423 if (typeof request.lastLoginAt !== 'undefined' &&
424 !validator.isNumber(request.lastLoginAt)) {
425 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_LAST_SIGN_IN_TIME);
426 }
427 // disableUser should be a boolean.
428 if (typeof request.disableUser !== 'undefined' &&
429 typeof request.disableUser !== 'boolean') {
430 // This is called disableUser on the backend but the developer specifies this as
431 // disabled externally. So the error message should use the client facing name.
432 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
433 }
434 // customAttributes should be stringified JSON with no blacklisted claims.
435 // The payload should not exceed 1KB.
436 if (typeof request.customAttributes !== 'undefined') {
437 var developerClaims_1;
438 try {
439 developerClaims_1 = JSON.parse(request.customAttributes);
440 }
441 catch (error) {
442 // JSON parsing error. This should never happen as we stringify the claims internally.
443 // However, we still need to check since setAccountInfo via edit requests could pass
444 // this field.
445 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CLAIMS, error.message);
446 }
447 var invalidClaims_1 = [];
448 // Check for any invalid claims.
449 exports.RESERVED_CLAIMS.forEach(function (blacklistedClaim) {
450 if (Object.prototype.hasOwnProperty.call(developerClaims_1, blacklistedClaim)) {
451 invalidClaims_1.push(blacklistedClaim);
452 }
453 });
454 // Throw an error if an invalid claim is detected.
455 if (invalidClaims_1.length > 0) {
456 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.FORBIDDEN_CLAIM, invalidClaims_1.length > 1 ?
457 "Developer claims \"" + invalidClaims_1.join('", "') + "\" are reserved and cannot be specified." :
458 "Developer claim \"" + invalidClaims_1[0] + "\" is reserved and cannot be specified.");
459 }
460 // Check claims payload does not exceed maxmimum size.
461 if (request.customAttributes.length > MAX_CLAIMS_PAYLOAD_SIZE) {
462 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.CLAIMS_TOO_LARGE, "Developer claims payload should not exceed " + MAX_CLAIMS_PAYLOAD_SIZE + " characters.");
463 }
464 }
465 // passwordHash has to be a base64 encoded string.
466 if (typeof request.passwordHash !== 'undefined' &&
467 !validator.isString(request.passwordHash)) {
468 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
469 }
470 // salt has to be a base64 encoded string.
471 if (typeof request.salt !== 'undefined' &&
472 !validator.isString(request.salt)) {
473 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
474 }
475 // providerUserInfo has to be an array of valid UserInfo requests.
476 if (typeof request.providerUserInfo !== 'undefined' &&
477 !validator.isArray(request.providerUserInfo)) {
478 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_DATA);
479 }
480 else if (validator.isArray(request.providerUserInfo)) {
481 request.providerUserInfo.forEach(function (providerUserInfoEntry) {
482 validateProviderUserInfo(providerUserInfoEntry);
483 });
484 }
485 // linkProviderUserInfo must be a (single) UserProvider value.
486 if (typeof request.linkProviderUserInfo !== 'undefined') {
487 validateProviderUserInfo(request.linkProviderUserInfo);
488 }
489 // mfaInfo is used for importUsers.
490 // mfa.enrollments is used for setAccountInfo.
491 // enrollments has to be an array of valid AuthFactorInfo requests.
492 var enrollments = null;
493 if (request.mfaInfo) {
494 enrollments = request.mfaInfo;
495 }
496 else if (request.mfa && request.mfa.enrollments) {
497 enrollments = request.mfa.enrollments;
498 }
499 if (enrollments) {
500 if (!validator.isArray(enrollments)) {
501 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLED_FACTORS);
502 }
503 enrollments.forEach(function (authFactorInfoEntry) {
504 validateAuthFactorInfo(authFactorInfoEntry);
505 });
506 }
507}
508/**
509 * Instantiates the createSessionCookie endpoint settings.
510 *
511 * @internal
512 */
513exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE = new api_request_1.ApiSettings(':createSessionCookie', 'POST')
514 // Set request validator.
515 .setRequestValidator(function (request) {
516 // Validate the ID token is a non-empty string.
517 if (!validator.isNonEmptyString(request.idToken)) {
518 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ID_TOKEN);
519 }
520 // Validate the custom session cookie duration.
521 if (!validator.isNumber(request.validDuration) ||
522 request.validDuration < MIN_SESSION_COOKIE_DURATION_SECS ||
523 request.validDuration > MAX_SESSION_COOKIE_DURATION_SECS) {
524 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
525 }
526})
527 // Set response validator.
528 .setResponseValidator(function (response) {
529 // Response should always contain the session cookie.
530 if (!validator.isNonEmptyString(response.sessionCookie)) {
531 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR);
532 }
533});
534/**
535 * Instantiates the uploadAccount endpoint settings.
536 *
537 * @internal
538 */
539exports.FIREBASE_AUTH_UPLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchCreate', 'POST');
540/**
541 * Instantiates the downloadAccount endpoint settings.
542 *
543 * @internal
544 */
545exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchGet', 'GET')
546 // Set request validator.
547 .setRequestValidator(function (request) {
548 // Validate next page token.
549 if (typeof request.nextPageToken !== 'undefined' &&
550 !validator.isNonEmptyString(request.nextPageToken)) {
551 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
552 }
553 // Validate max results.
554 if (!validator.isNumber(request.maxResults) ||
555 request.maxResults <= 0 ||
556 request.maxResults > MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE) {
557 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
558 (MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE + "."));
559 }
560});
561/**
562 * Instantiates the getAccountInfo endpoint settings.
563 *
564 * @internal
565 */
566exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
567 // Set request validator.
568 .setRequestValidator(function (request) {
569 if (!request.localId && !request.email && !request.phoneNumber && !request.federatedUserId) {
570 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
571 }
572})
573 // Set response validator.
574 .setResponseValidator(function (response) {
575 if (!response.users || !response.users.length) {
576 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
577 }
578});
579/**
580 * Instantiates the getAccountInfo endpoint settings for use when fetching info
581 * for multiple accounts.
582 *
583 * @internal
584 */
585exports.FIREBASE_AUTH_GET_ACCOUNTS_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
586 // Set request validator.
587 .setRequestValidator(function (request) {
588 if (!request.localId && !request.email && !request.phoneNumber && !request.federatedUserId) {
589 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
590 }
591});
592/**
593 * Instantiates the deleteAccount endpoint settings.
594 *
595 * @internal
596 */
597exports.FIREBASE_AUTH_DELETE_ACCOUNT = new api_request_1.ApiSettings('/accounts:delete', 'POST')
598 // Set request validator.
599 .setRequestValidator(function (request) {
600 if (!request.localId) {
601 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
602 }
603});
604/**
605 * @internal
606 */
607exports.FIREBASE_AUTH_BATCH_DELETE_ACCOUNTS = new api_request_1.ApiSettings('/accounts:batchDelete', 'POST')
608 .setRequestValidator(function (request) {
609 if (!request.localIds) {
610 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifiers');
611 }
612 if (typeof request.force === 'undefined' || request.force !== true) {
613 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing force=true field');
614 }
615})
616 .setResponseValidator(function (response) {
617 var errors = response.errors || [];
618 errors.forEach(function (batchDeleteErrorInfo) {
619 if (typeof batchDeleteErrorInfo.index === 'undefined') {
620 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server BatchDeleteAccountResponse is missing an errors.index field');
621 }
622 if (!batchDeleteErrorInfo.localId) {
623 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server BatchDeleteAccountResponse is missing an errors.localId field');
624 }
625 // Allow the (error) message to be missing/undef.
626 });
627});
628/**
629 * Instantiates the setAccountInfo endpoint settings for updating existing accounts.
630 *
631 * @internal
632 */
633exports.FIREBASE_AUTH_SET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:update', 'POST')
634 // Set request validator.
635 .setRequestValidator(function (request) {
636 // localId is a required parameter.
637 if (typeof request.localId === 'undefined') {
638 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
639 }
640 // Throw error when tenantId is passed in POST body.
641 if (typeof request.tenantId !== 'undefined') {
642 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "UpdateRequest" property.');
643 }
644 validateCreateEditRequest(request, WriteOperationType.Update);
645})
646 // Set response validator.
647 .setResponseValidator(function (response) {
648 // If the localId is not returned, then the request failed.
649 if (!response.localId) {
650 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
651 }
652});
653/**
654 * Instantiates the signupNewUser endpoint settings for creating a new user with or without
655 * uid being specified. The backend will create a new one if not provided and return it.
656 *
657 * @internal
658 */
659exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = new api_request_1.ApiSettings('/accounts', 'POST')
660 // Set request validator.
661 .setRequestValidator(function (request) {
662 // signupNewUser does not support customAttributes.
663 if (typeof request.customAttributes !== 'undefined') {
664 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"customAttributes" cannot be set when creating a new user.');
665 }
666 // signupNewUser does not support validSince.
667 if (typeof request.validSince !== 'undefined') {
668 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"validSince" cannot be set when creating a new user.');
669 }
670 // Throw error when tenantId is passed in POST body.
671 if (typeof request.tenantId !== 'undefined') {
672 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "CreateRequest" property.');
673 }
674 validateCreateEditRequest(request, WriteOperationType.Create);
675})
676 // Set response validator.
677 .setResponseValidator(function (response) {
678 // If the localId is not returned, then the request failed.
679 if (!response.localId) {
680 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new user');
681 }
682});
683var FIREBASE_AUTH_GET_OOB_CODE = new api_request_1.ApiSettings('/accounts:sendOobCode', 'POST')
684 // Set request validator.
685 .setRequestValidator(function (request) {
686 if (!validator.isEmail(request.email)) {
687 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
688 }
689 if (exports.EMAIL_ACTION_REQUEST_TYPES.indexOf(request.requestType) === -1) {
690 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"" + request.requestType + "\" is not a supported email action request type.");
691 }
692})
693 // Set response validator.
694 .setResponseValidator(function (response) {
695 // If the oobLink is not returned, then the request failed.
696 if (!response.oobLink) {
697 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create the email action link');
698 }
699});
700/**
701 * Instantiates the retrieve OIDC configuration endpoint settings.
702 *
703 * @internal
704 */
705var GET_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'GET')
706 // Set response validator.
707 .setResponseValidator(function (response) {
708 // Response should always contain the OIDC provider resource name.
709 if (!validator.isNonEmptyString(response.name)) {
710 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get OIDC configuration');
711 }
712});
713/**
714 * Instantiates the delete OIDC configuration endpoint settings.
715 *
716 * @internal
717 */
718var DELETE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'DELETE');
719/**
720 * Instantiates the create OIDC configuration endpoint settings.
721 *
722 * @internal
723 */
724var CREATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs?oauthIdpConfigId={providerId}', 'POST')
725 // Set response validator.
726 .setResponseValidator(function (response) {
727 // Response should always contain the OIDC provider resource name.
728 if (!validator.isNonEmptyString(response.name)) {
729 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC configuration');
730 }
731});
732/**
733 * Instantiates the update OIDC configuration endpoint settings.
734 *
735 * @internal
736 */
737var UPDATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
738 // Set response validator.
739 .setResponseValidator(function (response) {
740 // Response should always contain the configuration resource name.
741 if (!validator.isNonEmptyString(response.name)) {
742 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC configuration');
743 }
744});
745/**
746 * Instantiates the list OIDC configuration endpoint settings.
747 *
748 * @internal
749 */
750var LIST_OAUTH_IDP_CONFIGS = new api_request_1.ApiSettings('/oauthIdpConfigs', 'GET')
751 // Set request validator.
752 .setRequestValidator(function (request) {
753 // Validate next page token.
754 if (typeof request.pageToken !== 'undefined' &&
755 !validator.isNonEmptyString(request.pageToken)) {
756 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
757 }
758 // Validate max results.
759 if (!validator.isNumber(request.pageSize) ||
760 request.pageSize <= 0 ||
761 request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
762 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
763 (MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
764 }
765});
766/**
767 * Instantiates the retrieve SAML configuration endpoint settings.
768 *
769 * @internal
770 */
771var GET_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'GET')
772 // Set response validator.
773 .setResponseValidator(function (response) {
774 // Response should always contain the SAML provider resource name.
775 if (!validator.isNonEmptyString(response.name)) {
776 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get SAML configuration');
777 }
778});
779/**
780 * Instantiates the delete SAML configuration endpoint settings.
781 *
782 * @internal
783 */
784var DELETE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'DELETE');
785/**
786 * Instantiates the create SAML configuration endpoint settings.
787 *
788 * @internal
789 */
790var CREATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs?inboundSamlConfigId={providerId}', 'POST')
791 // Set response validator.
792 .setResponseValidator(function (response) {
793 // Response should always contain the SAML provider resource name.
794 if (!validator.isNonEmptyString(response.name)) {
795 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML configuration');
796 }
797});
798/**
799 * Instantiates the update SAML configuration endpoint settings.
800 *
801 * @internal
802 */
803var UPDATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
804 // Set response validator.
805 .setResponseValidator(function (response) {
806 // Response should always contain the configuration resource name.
807 if (!validator.isNonEmptyString(response.name)) {
808 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML configuration');
809 }
810});
811/**
812 * Instantiates the list SAML configuration endpoint settings.
813 *
814 * @internal
815 */
816var LIST_INBOUND_SAML_CONFIGS = new api_request_1.ApiSettings('/inboundSamlConfigs', 'GET')
817 // Set request validator.
818 .setRequestValidator(function (request) {
819 // Validate next page token.
820 if (typeof request.pageToken !== 'undefined' &&
821 !validator.isNonEmptyString(request.pageToken)) {
822 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
823 }
824 // Validate max results.
825 if (!validator.isNumber(request.pageSize) ||
826 request.pageSize <= 0 ||
827 request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
828 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
829 (MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
830 }
831});
832/**
833 * Class that provides the mechanism to send requests to the Firebase Auth backend endpoints.
834 *
835 * @internal
836 */
837var AbstractAuthRequestHandler = /** @class */ (function () {
838 /**
839 * @param app - The app used to fetch access tokens to sign API requests.
840 * @constructor
841 */
842 function AbstractAuthRequestHandler(app) {
843 this.app = app;
844 if (typeof app !== 'object' || app === null || !('options' in app)) {
845 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.auth() must be a valid Firebase app instance.');
846 }
847 this.httpClient = new AuthHttpClient(app);
848 }
849 /**
850 * @param response - The response to check for errors.
851 * @returns The error code if present; null otherwise.
852 */
853 AbstractAuthRequestHandler.getErrorCode = function (response) {
854 return (validator.isNonNullObject(response) && response.error && response.error.message) || null;
855 };
856 AbstractAuthRequestHandler.addUidToRequest = function (id, request) {
857 if (!validator.isUid(id.uid)) {
858 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
859 }
860 request.localId ? request.localId.push(id.uid) : request.localId = [id.uid];
861 return request;
862 };
863 AbstractAuthRequestHandler.addEmailToRequest = function (id, request) {
864 if (!validator.isEmail(id.email)) {
865 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
866 }
867 request.email ? request.email.push(id.email) : request.email = [id.email];
868 return request;
869 };
870 AbstractAuthRequestHandler.addPhoneToRequest = function (id, request) {
871 if (!validator.isPhoneNumber(id.phoneNumber)) {
872 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER);
873 }
874 request.phoneNumber ? request.phoneNumber.push(id.phoneNumber) : request.phoneNumber = [id.phoneNumber];
875 return request;
876 };
877 AbstractAuthRequestHandler.addProviderToRequest = function (id, request) {
878 if (!validator.isNonEmptyString(id.providerId)) {
879 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
880 }
881 if (!validator.isNonEmptyString(id.providerUid)) {
882 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_UID);
883 }
884 var federatedUserId = {
885 providerId: id.providerId,
886 rawId: id.providerUid,
887 };
888 request.federatedUserId
889 ? request.federatedUserId.push(federatedUserId)
890 : request.federatedUserId = [federatedUserId];
891 return request;
892 };
893 /**
894 * Creates a new Firebase session cookie with the specified duration that can be used for
895 * session management (set as a server side session cookie with custom cookie policy).
896 * The session cookie JWT will have the same payload claims as the provided ID token.
897 *
898 * @param idToken - The Firebase ID token to exchange for a session cookie.
899 * @param expiresIn - The session cookie duration in milliseconds.
900 *
901 * @returns A promise that resolves on success with the created session cookie.
902 */
903 AbstractAuthRequestHandler.prototype.createSessionCookie = function (idToken, expiresIn) {
904 var request = {
905 idToken: idToken,
906 // Convert to seconds.
907 validDuration: expiresIn / 1000,
908 };
909 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE, request)
910 .then(function (response) { return response.sessionCookie; });
911 };
912 /**
913 * Looks up a user by uid.
914 *
915 * @param uid - The uid of the user to lookup.
916 * @returns A promise that resolves with the user information.
917 */
918 AbstractAuthRequestHandler.prototype.getAccountInfoByUid = function (uid) {
919 if (!validator.isUid(uid)) {
920 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
921 }
922 var request = {
923 localId: [uid],
924 };
925 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
926 };
927 /**
928 * Looks up a user by email.
929 *
930 * @param email - The email of the user to lookup.
931 * @returns A promise that resolves with the user information.
932 */
933 AbstractAuthRequestHandler.prototype.getAccountInfoByEmail = function (email) {
934 if (!validator.isEmail(email)) {
935 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL));
936 }
937 var request = {
938 email: [email],
939 };
940 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
941 };
942 /**
943 * Looks up a user by phone number.
944 *
945 * @param phoneNumber - The phone number of the user to lookup.
946 * @returns A promise that resolves with the user information.
947 */
948 AbstractAuthRequestHandler.prototype.getAccountInfoByPhoneNumber = function (phoneNumber) {
949 if (!validator.isPhoneNumber(phoneNumber)) {
950 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER));
951 }
952 var request = {
953 phoneNumber: [phoneNumber],
954 };
955 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
956 };
957 AbstractAuthRequestHandler.prototype.getAccountInfoByFederatedUid = function (providerId, rawId) {
958 if (!validator.isNonEmptyString(providerId) || !validator.isNonEmptyString(rawId)) {
959 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
960 }
961 var request = {
962 federatedUserId: [{
963 providerId: providerId,
964 rawId: rawId,
965 }],
966 };
967 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
968 };
969 /**
970 * Looks up multiple users by their identifiers (uid, email, etc).
971 *
972 * @param identifiers - The identifiers indicating the users
973 * to be looked up. Must have <= 100 entries.
974 * @param A - promise that resolves with the set of successfully
975 * looked up users. Possibly empty if no users were looked up.
976 */
977 AbstractAuthRequestHandler.prototype.getAccountInfoByIdentifiers = function (identifiers) {
978 if (identifiers.length === 0) {
979 return Promise.resolve({ users: [] });
980 }
981 else if (identifiers.length > MAX_GET_ACCOUNTS_BATCH_SIZE) {
982 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, '`identifiers` parameter must have <= ' + MAX_GET_ACCOUNTS_BATCH_SIZE + ' entries.');
983 }
984 var request = {};
985 for (var _i = 0, identifiers_1 = identifiers; _i < identifiers_1.length; _i++) {
986 var id = identifiers_1[_i];
987 if (identifier_1.isUidIdentifier(id)) {
988 request = AbstractAuthRequestHandler.addUidToRequest(id, request);
989 }
990 else if (identifier_1.isEmailIdentifier(id)) {
991 request = AbstractAuthRequestHandler.addEmailToRequest(id, request);
992 }
993 else if (identifier_1.isPhoneIdentifier(id)) {
994 request = AbstractAuthRequestHandler.addPhoneToRequest(id, request);
995 }
996 else if (identifier_1.isProviderIdentifier(id)) {
997 request = AbstractAuthRequestHandler.addProviderToRequest(id, request);
998 }
999 else {
1000 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Unrecognized identifier: ' + id);
1001 }
1002 }
1003 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNTS_INFO, request);
1004 };
1005 /**
1006 * Exports the users (single batch only) with a size of maxResults and starting from
1007 * the offset as specified by pageToken.
1008 *
1009 * @param maxResults - The page size, 1000 if undefined. This is also the maximum
1010 * allowed limit.
1011 * @param pageToken - The next page token. If not specified, returns users starting
1012 * without any offset. Users are returned in the order they were created from oldest to
1013 * newest, relative to the page token offset.
1014 * @returns A promise that resolves with the current batch of downloaded
1015 * users and the next page token if available. For the last page, an empty list of users
1016 * and no page token are returned.
1017 */
1018 AbstractAuthRequestHandler.prototype.downloadAccount = function (maxResults, pageToken) {
1019 if (maxResults === void 0) { maxResults = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE; }
1020 // Construct request.
1021 var request = {
1022 maxResults: maxResults,
1023 nextPageToken: pageToken,
1024 };
1025 // Remove next page token if not provided.
1026 if (typeof request.nextPageToken === 'undefined') {
1027 delete request.nextPageToken;
1028 }
1029 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT, request)
1030 .then(function (response) {
1031 // No more users available.
1032 if (!response.users) {
1033 response.users = [];
1034 }
1035 return response;
1036 });
1037 };
1038 /**
1039 * Imports the list of users provided to Firebase Auth. This is useful when
1040 * migrating from an external authentication system without having to use the Firebase CLI SDK.
1041 * At most, 1000 users are allowed to be imported one at a time.
1042 * When importing a list of password users, UserImportOptions are required to be specified.
1043 *
1044 * @param users - The list of user records to import to Firebase Auth.
1045 * @param options - The user import options, required when the users provided
1046 * include password credentials.
1047 * @returns A promise that resolves when the operation completes
1048 * with the result of the import. This includes the number of successful imports, the number
1049 * of failed uploads and their corresponding errors.
1050 */
1051 AbstractAuthRequestHandler.prototype.uploadAccount = function (users, options) {
1052 // This will throw if any error is detected in the hash options.
1053 // For errors in the list of users, this will not throw and will report the errors and the
1054 // corresponding user index in the user import generated response below.
1055 // No need to validate raw request or raw response as this is done in UserImportBuilder.
1056 var userImportBuilder = new user_import_builder_1.UserImportBuilder(users, options, function (userRequest) {
1057 // Pass true to validate the uploadAccount specific fields.
1058 validateCreateEditRequest(userRequest, WriteOperationType.Upload);
1059 });
1060 var request = userImportBuilder.buildRequest();
1061 // Fail quickly if more users than allowed are to be imported.
1062 if (validator.isArray(users) && users.length > MAX_UPLOAD_ACCOUNT_BATCH_SIZE) {
1063 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.");
1064 }
1065 // If no remaining user in request after client side processing, there is no need
1066 // to send the request to the server.
1067 if (!request.users || request.users.length === 0) {
1068 return Promise.resolve(userImportBuilder.buildResponse([]));
1069 }
1070 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_UPLOAD_ACCOUNT, request)
1071 .then(function (response) {
1072 // No error object is returned if no error encountered.
1073 var failedUploads = (response.error || []);
1074 // Rewrite response as UserImportResult and re-insert client previously detected errors.
1075 return userImportBuilder.buildResponse(failedUploads);
1076 });
1077 };
1078 /**
1079 * Deletes an account identified by a uid.
1080 *
1081 * @param uid - The uid of the user to delete.
1082 * @returns A promise that resolves when the user is deleted.
1083 */
1084 AbstractAuthRequestHandler.prototype.deleteAccount = function (uid) {
1085 if (!validator.isUid(uid)) {
1086 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
1087 }
1088 var request = {
1089 localId: uid,
1090 };
1091 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_DELETE_ACCOUNT, request);
1092 };
1093 AbstractAuthRequestHandler.prototype.deleteAccounts = function (uids, force) {
1094 if (uids.length === 0) {
1095 return Promise.resolve({});
1096 }
1097 else if (uids.length > MAX_DELETE_ACCOUNTS_BATCH_SIZE) {
1098 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, '`uids` parameter must have <= ' + MAX_DELETE_ACCOUNTS_BATCH_SIZE + ' entries.');
1099 }
1100 var request = {
1101 localIds: [],
1102 force: force,
1103 };
1104 uids.forEach(function (uid) {
1105 if (!validator.isUid(uid)) {
1106 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
1107 }
1108 request.localIds.push(uid);
1109 });
1110 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_BATCH_DELETE_ACCOUNTS, request);
1111 };
1112 /**
1113 * Sets additional developer claims on an existing user identified by provided UID.
1114 *
1115 * @param uid - The user to edit.
1116 * @param customUserClaims - The developer claims to set.
1117 * @returns A promise that resolves when the operation completes
1118 * with the user id that was edited.
1119 */
1120 AbstractAuthRequestHandler.prototype.setCustomUserClaims = function (uid, customUserClaims) {
1121 // Validate user UID.
1122 if (!validator.isUid(uid)) {
1123 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
1124 }
1125 else if (!validator.isObject(customUserClaims)) {
1126 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'CustomUserClaims argument must be an object or null.'));
1127 }
1128 // Delete operation. Replace null with an empty object.
1129 if (customUserClaims === null) {
1130 customUserClaims = {};
1131 }
1132 // Construct custom user attribute editting request.
1133 var request = {
1134 localId: uid,
1135 customAttributes: JSON.stringify(customUserClaims),
1136 };
1137 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
1138 .then(function (response) {
1139 return response.localId;
1140 });
1141 };
1142 /**
1143 * Edits an existing user.
1144 *
1145 * @param uid - The user to edit.
1146 * @param properties - The properties to set on the user.
1147 * @returns A promise that resolves when the operation completes
1148 * with the user id that was edited.
1149 */
1150 AbstractAuthRequestHandler.prototype.updateExistingAccount = function (uid, properties) {
1151 if (!validator.isUid(uid)) {
1152 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
1153 }
1154 else if (!validator.isNonNullObject(properties)) {
1155 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
1156 }
1157 else if (validator.isNonNullObject(properties.providerToLink)) {
1158 // TODO(rsgowman): These checks overlap somewhat with
1159 // validateProviderUserInfo. It may be possible to refactor a bit.
1160 if (!validator.isNonEmptyString(properties.providerToLink.providerId)) {
1161 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.providerId of properties argument must be a non-empty string.');
1162 }
1163 if (!validator.isNonEmptyString(properties.providerToLink.uid)) {
1164 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.uid of properties argument must be a non-empty string.');
1165 }
1166 }
1167 else if (typeof properties.providersToUnlink !== 'undefined') {
1168 if (!validator.isArray(properties.providersToUnlink)) {
1169 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
1170 }
1171 properties.providersToUnlink.forEach(function (providerId) {
1172 if (!validator.isNonEmptyString(providerId)) {
1173 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
1174 }
1175 });
1176 }
1177 // Build the setAccountInfo request.
1178 var request = deep_copy_1.deepCopy(properties);
1179 request.localId = uid;
1180 // For deleting displayName or photoURL, these values must be passed as null.
1181 // They will be removed from the backend request and an additional parameter
1182 // deleteAttribute: ['PHOTO_URL', 'DISPLAY_NAME']
1183 // with an array of the parameter names to delete will be passed.
1184 // Parameters that are deletable and their deleteAttribute names.
1185 // Use client facing names, photoURL instead of photoUrl.
1186 var deletableParams = {
1187 displayName: 'DISPLAY_NAME',
1188 photoURL: 'PHOTO_URL',
1189 };
1190 // Properties to delete if available.
1191 request.deleteAttribute = [];
1192 for (var key in deletableParams) {
1193 if (request[key] === null) {
1194 // Add property identifier to list of attributes to delete.
1195 request.deleteAttribute.push(deletableParams[key]);
1196 // Remove property from request.
1197 delete request[key];
1198 }
1199 }
1200 if (request.deleteAttribute.length === 0) {
1201 delete request.deleteAttribute;
1202 }
1203 // For deleting phoneNumber, this value must be passed as null.
1204 // It will be removed from the backend request and an additional parameter
1205 // deleteProvider: ['phone'] with an array of providerIds (phone in this case),
1206 // will be passed.
1207 if (request.phoneNumber === null) {
1208 request.deleteProvider ? request.deleteProvider.push('phone') : request.deleteProvider = ['phone'];
1209 delete request.phoneNumber;
1210 }
1211 if (typeof (request.providerToLink) !== 'undefined') {
1212 request.linkProviderUserInfo = deep_copy_1.deepCopy(request.providerToLink);
1213 delete request.providerToLink;
1214 request.linkProviderUserInfo.rawId = request.linkProviderUserInfo.uid;
1215 delete request.linkProviderUserInfo.uid;
1216 }
1217 if (typeof (request.providersToUnlink) !== 'undefined') {
1218 if (!validator.isArray(request.deleteProvider)) {
1219 request.deleteProvider = [];
1220 }
1221 request.deleteProvider = request.deleteProvider.concat(request.providersToUnlink);
1222 delete request.providersToUnlink;
1223 }
1224 // Rewrite photoURL to photoUrl.
1225 if (typeof request.photoURL !== 'undefined') {
1226 request.photoUrl = request.photoURL;
1227 delete request.photoURL;
1228 }
1229 // Rewrite disabled to disableUser.
1230 if (typeof request.disabled !== 'undefined') {
1231 request.disableUser = request.disabled;
1232 delete request.disabled;
1233 }
1234 // Construct mfa related user data.
1235 if (validator.isNonNullObject(request.multiFactor)) {
1236 if (request.multiFactor.enrolledFactors === null) {
1237 // Remove all second factors.
1238 request.mfa = {};
1239 }
1240 else if (validator.isArray(request.multiFactor.enrolledFactors)) {
1241 request.mfa = {
1242 enrollments: [],
1243 };
1244 try {
1245 request.multiFactor.enrolledFactors.forEach(function (multiFactorInfo) {
1246 request.mfa.enrollments.push(user_import_builder_1.convertMultiFactorInfoToServerFormat(multiFactorInfo));
1247 });
1248 }
1249 catch (e) {
1250 return Promise.reject(e);
1251 }
1252 if (request.mfa.enrollments.length === 0) {
1253 delete request.mfa.enrollments;
1254 }
1255 }
1256 delete request.multiFactor;
1257 }
1258 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
1259 .then(function (response) {
1260 return response.localId;
1261 });
1262 };
1263 /**
1264 * Revokes all refresh tokens for the specified user identified by the uid provided.
1265 * In addition to revoking all refresh tokens for a user, all ID tokens issued
1266 * before revocation will also be revoked on the Auth backend. Any request with an
1267 * ID token generated before revocation will be rejected with a token expired error.
1268 * Note that due to the fact that the timestamp is stored in seconds, any tokens minted in
1269 * the same second as the revocation will still be valid. If there is a chance that a token
1270 * was minted in the last second, delay for 1 second before revoking.
1271 *
1272 * @param uid - The user whose tokens are to be revoked.
1273 * @returns A promise that resolves when the operation completes
1274 * successfully with the user id of the corresponding user.
1275 */
1276 AbstractAuthRequestHandler.prototype.revokeRefreshTokens = function (uid) {
1277 // Validate user UID.
1278 if (!validator.isUid(uid)) {
1279 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
1280 }
1281 var request = {
1282 localId: uid,
1283 // validSince is in UTC seconds.
1284 validSince: Math.floor(new Date().getTime() / 1000),
1285 };
1286 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
1287 .then(function (response) {
1288 return response.localId;
1289 });
1290 };
1291 /**
1292 * Create a new user with the properties supplied.
1293 *
1294 * @param properties - The properties to set on the user.
1295 * @returns A promise that resolves when the operation completes
1296 * with the user id that was created.
1297 */
1298 AbstractAuthRequestHandler.prototype.createNewAccount = function (properties) {
1299 if (!validator.isNonNullObject(properties)) {
1300 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
1301 }
1302 var request = deep_copy_1.deepCopy(properties);
1303 // Rewrite photoURL to photoUrl.
1304 if (typeof request.photoURL !== 'undefined') {
1305 request.photoUrl = request.photoURL;
1306 delete request.photoURL;
1307 }
1308 // Rewrite uid to localId if it exists.
1309 if (typeof request.uid !== 'undefined') {
1310 request.localId = request.uid;
1311 delete request.uid;
1312 }
1313 // Construct mfa related user data.
1314 if (validator.isNonNullObject(request.multiFactor)) {
1315 if (validator.isNonEmptyArray(request.multiFactor.enrolledFactors)) {
1316 var mfaInfo_1 = [];
1317 try {
1318 request.multiFactor.enrolledFactors.forEach(function (multiFactorInfo) {
1319 // Enrollment time and uid are not allowed for signupNewUser endpoint.
1320 // They will automatically be provisioned server side.
1321 if ('enrollmentTime' in multiFactorInfo) {
1322 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"enrollmentTime" is not supported when adding second factors via "createUser()"');
1323 }
1324 else if ('uid' in multiFactorInfo) {
1325 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"uid" is not supported when adding second factors via "createUser()"');
1326 }
1327 mfaInfo_1.push(user_import_builder_1.convertMultiFactorInfoToServerFormat(multiFactorInfo));
1328 });
1329 }
1330 catch (e) {
1331 return Promise.reject(e);
1332 }
1333 request.mfaInfo = mfaInfo_1;
1334 }
1335 delete request.multiFactor;
1336 }
1337 return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SIGN_UP_NEW_USER, request)
1338 .then(function (response) {
1339 // Return the user id.
1340 return response.localId;
1341 });
1342 };
1343 /**
1344 * Generates the out of band email action link for the email specified using the action code settings provided.
1345 * Returns a promise that resolves with the generated link.
1346 *
1347 * @param requestType - The request type. This could be either used for password reset,
1348 * email verification, email link sign-in.
1349 * @param email - The email of the user the link is being sent to.
1350 * @param actionCodeSettings - The optional action code setings which defines whether
1351 * the link is to be handled by a mobile app and the additional state information to be passed in the
1352 * deep link, etc. Required when requestType == 'EMAIL_SIGNIN'
1353 * @returns A promise that resolves with the email action link.
1354 */
1355 AbstractAuthRequestHandler.prototype.getEmailActionLink = function (requestType, email, actionCodeSettings) {
1356 var request = { requestType: requestType, email: email, returnOobLink: true };
1357 // ActionCodeSettings required for email link sign-in to determine the url where the sign-in will
1358 // be completed.
1359 if (typeof actionCodeSettings === 'undefined' && requestType === 'EMAIL_SIGNIN') {
1360 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "`actionCodeSettings` is required when `requestType` === 'EMAIL_SIGNIN'"));
1361 }
1362 if (typeof actionCodeSettings !== 'undefined' || requestType === 'EMAIL_SIGNIN') {
1363 try {
1364 var builder = new action_code_settings_builder_1.ActionCodeSettingsBuilder(actionCodeSettings);
1365 request = deep_copy_1.deepExtend(request, builder.buildRequest());
1366 }
1367 catch (e) {
1368 return Promise.reject(e);
1369 }
1370 }
1371 return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_GET_OOB_CODE, request)
1372 .then(function (response) {
1373 // Return the link.
1374 return response.oobLink;
1375 });
1376 };
1377 /**
1378 * Looks up an OIDC provider configuration by provider ID.
1379 *
1380 * @param providerId - The provider identifier of the configuration to lookup.
1381 * @returns A promise that resolves with the provider configuration information.
1382 */
1383 AbstractAuthRequestHandler.prototype.getOAuthIdpConfig = function (providerId) {
1384 if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
1385 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1386 }
1387 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_OAUTH_IDP_CONFIG, {}, { providerId: providerId });
1388 };
1389 /**
1390 * Lists the OIDC configurations (single batch only) with a size of maxResults and starting from
1391 * the offset as specified by pageToken.
1392 *
1393 * @param maxResults - The page size, 100 if undefined. This is also the maximum
1394 * allowed limit.
1395 * @param pageToken - The next page token. If not specified, returns OIDC configurations
1396 * without any offset. Configurations are returned in the order they were created from oldest to
1397 * newest, relative to the page token offset.
1398 * @returns A promise that resolves with the current batch of downloaded
1399 * OIDC configurations and the next page token if available. For the last page, an empty list of provider
1400 * configuration and no page token are returned.
1401 */
1402 AbstractAuthRequestHandler.prototype.listOAuthIdpConfigs = function (maxResults, pageToken) {
1403 if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
1404 var request = {
1405 pageSize: maxResults,
1406 };
1407 // Add next page token if provided.
1408 if (typeof pageToken !== 'undefined') {
1409 request.pageToken = pageToken;
1410 }
1411 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_OAUTH_IDP_CONFIGS, request)
1412 .then(function (response) {
1413 if (!response.oauthIdpConfigs) {
1414 response.oauthIdpConfigs = [];
1415 delete response.nextPageToken;
1416 }
1417 return response;
1418 });
1419 };
1420 /**
1421 * Deletes an OIDC configuration identified by a providerId.
1422 *
1423 * @param providerId - The identifier of the OIDC configuration to delete.
1424 * @returns A promise that resolves when the OIDC provider is deleted.
1425 */
1426 AbstractAuthRequestHandler.prototype.deleteOAuthIdpConfig = function (providerId) {
1427 if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
1428 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1429 }
1430 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_OAUTH_IDP_CONFIG, {}, { providerId: providerId })
1431 .then(function () {
1432 // Return nothing.
1433 });
1434 };
1435 /**
1436 * Creates a new OIDC provider configuration with the properties provided.
1437 *
1438 * @param options - The properties to set on the new OIDC provider configuration to be created.
1439 * @returns A promise that resolves with the newly created OIDC
1440 * configuration.
1441 */
1442 AbstractAuthRequestHandler.prototype.createOAuthIdpConfig = function (options) {
1443 // Construct backend request.
1444 var request;
1445 try {
1446 request = auth_config_1.OIDCConfig.buildServerRequest(options) || {};
1447 }
1448 catch (e) {
1449 return Promise.reject(e);
1450 }
1451 var providerId = options.providerId;
1452 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_OAUTH_IDP_CONFIG, request, { providerId: providerId })
1453 .then(function (response) {
1454 if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
1455 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC provider configuration');
1456 }
1457 return response;
1458 });
1459 };
1460 /**
1461 * Updates an existing OIDC provider configuration with the properties provided.
1462 *
1463 * @param providerId - The provider identifier of the OIDC configuration to update.
1464 * @param options - The properties to update on the existing configuration.
1465 * @returns A promise that resolves with the modified provider
1466 * configuration.
1467 */
1468 AbstractAuthRequestHandler.prototype.updateOAuthIdpConfig = function (providerId, options) {
1469 if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
1470 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1471 }
1472 // Construct backend request.
1473 var request;
1474 try {
1475 request = auth_config_1.OIDCConfig.buildServerRequest(options, true) || {};
1476 }
1477 catch (e) {
1478 return Promise.reject(e);
1479 }
1480 var updateMask = utils.generateUpdateMask(request);
1481 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_OAUTH_IDP_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
1482 .then(function (response) {
1483 if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
1484 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC provider configuration');
1485 }
1486 return response;
1487 });
1488 };
1489 /**
1490 * Looks up an SAML provider configuration by provider ID.
1491 *
1492 * @param providerId - The provider identifier of the configuration to lookup.
1493 * @returns A promise that resolves with the provider configuration information.
1494 */
1495 AbstractAuthRequestHandler.prototype.getInboundSamlConfig = function (providerId) {
1496 if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
1497 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1498 }
1499 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_INBOUND_SAML_CONFIG, {}, { providerId: providerId });
1500 };
1501 /**
1502 * Lists the SAML configurations (single batch only) with a size of maxResults and starting from
1503 * the offset as specified by pageToken.
1504 *
1505 * @param maxResults - The page size, 100 if undefined. This is also the maximum
1506 * allowed limit.
1507 * @param pageToken - The next page token. If not specified, returns SAML configurations starting
1508 * without any offset. Configurations are returned in the order they were created from oldest to
1509 * newest, relative to the page token offset.
1510 * @returns A promise that resolves with the current batch of downloaded
1511 * SAML configurations and the next page token if available. For the last page, an empty list of provider
1512 * configuration and no page token are returned.
1513 */
1514 AbstractAuthRequestHandler.prototype.listInboundSamlConfigs = function (maxResults, pageToken) {
1515 if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
1516 var request = {
1517 pageSize: maxResults,
1518 };
1519 // Add next page token if provided.
1520 if (typeof pageToken !== 'undefined') {
1521 request.pageToken = pageToken;
1522 }
1523 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_INBOUND_SAML_CONFIGS, request)
1524 .then(function (response) {
1525 if (!response.inboundSamlConfigs) {
1526 response.inboundSamlConfigs = [];
1527 delete response.nextPageToken;
1528 }
1529 return response;
1530 });
1531 };
1532 /**
1533 * Deletes a SAML configuration identified by a providerId.
1534 *
1535 * @param providerId - The identifier of the SAML configuration to delete.
1536 * @returns A promise that resolves when the SAML provider is deleted.
1537 */
1538 AbstractAuthRequestHandler.prototype.deleteInboundSamlConfig = function (providerId) {
1539 if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
1540 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1541 }
1542 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_INBOUND_SAML_CONFIG, {}, { providerId: providerId })
1543 .then(function () {
1544 // Return nothing.
1545 });
1546 };
1547 /**
1548 * Creates a new SAML provider configuration with the properties provided.
1549 *
1550 * @param options - The properties to set on the new SAML provider configuration to be created.
1551 * @returns A promise that resolves with the newly created SAML
1552 * configuration.
1553 */
1554 AbstractAuthRequestHandler.prototype.createInboundSamlConfig = function (options) {
1555 // Construct backend request.
1556 var request;
1557 try {
1558 request = auth_config_1.SAMLConfig.buildServerRequest(options) || {};
1559 }
1560 catch (e) {
1561 return Promise.reject(e);
1562 }
1563 var providerId = options.providerId;
1564 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_INBOUND_SAML_CONFIG, request, { providerId: providerId })
1565 .then(function (response) {
1566 if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
1567 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML provider configuration');
1568 }
1569 return response;
1570 });
1571 };
1572 /**
1573 * Updates an existing SAML provider configuration with the properties provided.
1574 *
1575 * @param providerId - The provider identifier of the SAML configuration to update.
1576 * @param options - The properties to update on the existing configuration.
1577 * @returns A promise that resolves with the modified provider
1578 * configuration.
1579 */
1580 AbstractAuthRequestHandler.prototype.updateInboundSamlConfig = function (providerId, options) {
1581 if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
1582 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
1583 }
1584 // Construct backend request.
1585 var request;
1586 try {
1587 request = auth_config_1.SAMLConfig.buildServerRequest(options, true) || {};
1588 }
1589 catch (e) {
1590 return Promise.reject(e);
1591 }
1592 var updateMask = utils.generateUpdateMask(request);
1593 return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_INBOUND_SAML_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
1594 .then(function (response) {
1595 if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
1596 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML provider configuration');
1597 }
1598 return response;
1599 });
1600 };
1601 /**
1602 * Invokes the request handler based on the API settings object passed.
1603 *
1604 * @param urlBuilder - The URL builder for Auth endpoints.
1605 * @param apiSettings - The API endpoint settings to apply to request and response.
1606 * @param requestData - The request data.
1607 * @param additionalResourceParams - Additional resource related params if needed.
1608 * @returns A promise that resolves with the response.
1609 */
1610 AbstractAuthRequestHandler.prototype.invokeRequestHandler = function (urlBuilder, apiSettings, requestData, additionalResourceParams) {
1611 var _this = this;
1612 return urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams)
1613 .then(function (url) {
1614 // Validate request.
1615 var requestValidator = apiSettings.getRequestValidator();
1616 requestValidator(requestData);
1617 // Process request.
1618 var req = {
1619 method: apiSettings.getHttpMethod(),
1620 url: url,
1621 headers: FIREBASE_AUTH_HEADER,
1622 data: requestData,
1623 timeout: FIREBASE_AUTH_TIMEOUT,
1624 };
1625 return _this.httpClient.send(req);
1626 })
1627 .then(function (response) {
1628 // Validate response.
1629 var responseValidator = apiSettings.getResponseValidator();
1630 responseValidator(response.data);
1631 // Return entire response.
1632 return response.data;
1633 })
1634 .catch(function (err) {
1635 if (err instanceof api_request_1.HttpError) {
1636 var error = err.response.data;
1637 var errorCode = AbstractAuthRequestHandler.getErrorCode(error);
1638 if (!errorCode) {
1639 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Error returned from server: ' + error + '. Additionally, an ' +
1640 'internal error occurred while attempting to extract the ' +
1641 'errorcode from the error.');
1642 }
1643 throw error_1.FirebaseAuthError.fromServerError(errorCode, /* message */ undefined, error);
1644 }
1645 throw err;
1646 });
1647 };
1648 /**
1649 * @returns The current Auth user management resource URL builder.
1650 */
1651 AbstractAuthRequestHandler.prototype.getAuthUrlBuilder = function () {
1652 if (!this.authUrlBuilder) {
1653 this.authUrlBuilder = this.newAuthUrlBuilder();
1654 }
1655 return this.authUrlBuilder;
1656 };
1657 /**
1658 * @returns The current project config resource URL builder.
1659 */
1660 AbstractAuthRequestHandler.prototype.getProjectConfigUrlBuilder = function () {
1661 if (!this.projectConfigUrlBuilder) {
1662 this.projectConfigUrlBuilder = this.newProjectConfigUrlBuilder();
1663 }
1664 return this.projectConfigUrlBuilder;
1665 };
1666 return AbstractAuthRequestHandler;
1667}());
1668exports.AbstractAuthRequestHandler = AbstractAuthRequestHandler;
1669/** Instantiates the getTenant endpoint settings. */
1670var GET_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'GET')
1671 // Set response validator.
1672 .setResponseValidator(function (response) {
1673 // Response should always contain at least the tenant name.
1674 if (!validator.isNonEmptyString(response.name)) {
1675 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get tenant');
1676 }
1677});
1678/** Instantiates the deleteTenant endpoint settings. */
1679var DELETE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'DELETE');
1680/** Instantiates the updateTenant endpoint settings. */
1681var UPDATE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}?updateMask={updateMask}', 'PATCH')
1682 // Set response validator.
1683 .setResponseValidator(function (response) {
1684 // Response should always contain at least the tenant name.
1685 if (!validator.isNonEmptyString(response.name) ||
1686 !tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
1687 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update tenant');
1688 }
1689});
1690/** Instantiates the listTenants endpoint settings. */
1691var LIST_TENANTS = new api_request_1.ApiSettings('/tenants', 'GET')
1692 // Set request validator.
1693 .setRequestValidator(function (request) {
1694 // Validate next page token.
1695 if (typeof request.pageToken !== 'undefined' &&
1696 !validator.isNonEmptyString(request.pageToken)) {
1697 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
1698 }
1699 // Validate max results.
1700 if (!validator.isNumber(request.pageSize) ||
1701 request.pageSize <= 0 ||
1702 request.pageSize > MAX_LIST_TENANT_PAGE_SIZE) {
1703 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive non-zero number that does not exceed ' +
1704 ("the allowed " + MAX_LIST_TENANT_PAGE_SIZE + "."));
1705 }
1706});
1707/** Instantiates the createTenant endpoint settings. */
1708var CREATE_TENANT = new api_request_1.ApiSettings('/tenants', 'POST')
1709 // Set response validator.
1710 .setResponseValidator(function (response) {
1711 // Response should always contain at least the tenant name.
1712 if (!validator.isNonEmptyString(response.name) ||
1713 !tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
1714 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new tenant');
1715 }
1716});
1717/**
1718 * Utility for sending requests to Auth server that are Auth instance related. This includes user and
1719 * tenant management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
1720 * additional tenant management related APIs.
1721 */
1722var AuthRequestHandler = /** @class */ (function (_super) {
1723 __extends(AuthRequestHandler, _super);
1724 /**
1725 * The FirebaseAuthRequestHandler constructor used to initialize an instance using a FirebaseApp.
1726 *
1727 * @param app - The app used to fetch access tokens to sign API requests.
1728 * @constructor.
1729 */
1730 function AuthRequestHandler(app) {
1731 var _this = _super.call(this, app) || this;
1732 _this.tenantMgmtResourceBuilder = new AuthResourceUrlBuilder(app, 'v2');
1733 return _this;
1734 }
1735 /**
1736 * @returns A new Auth user management resource URL builder instance.
1737 */
1738 AuthRequestHandler.prototype.newAuthUrlBuilder = function () {
1739 return new AuthResourceUrlBuilder(this.app, 'v1');
1740 };
1741 /**
1742 * @returns A new project config resource URL builder instance.
1743 */
1744 AuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
1745 return new AuthResourceUrlBuilder(this.app, 'v2');
1746 };
1747 /**
1748 * Looks up a tenant by tenant ID.
1749 *
1750 * @param tenantId - The tenant identifier of the tenant to lookup.
1751 * @returns A promise that resolves with the tenant information.
1752 */
1753 AuthRequestHandler.prototype.getTenant = function (tenantId) {
1754 if (!validator.isNonEmptyString(tenantId)) {
1755 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
1756 }
1757 return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, GET_TENANT, {}, { tenantId: tenantId })
1758 .then(function (response) {
1759 return response;
1760 });
1761 };
1762 /**
1763 * Exports the tenants (single batch only) with a size of maxResults and starting from
1764 * the offset as specified by pageToken.
1765 *
1766 * @param maxResults - The page size, 1000 if undefined. This is also the maximum
1767 * allowed limit.
1768 * @param pageToken - The next page token. If not specified, returns tenants starting
1769 * without any offset. Tenants are returned in the order they were created from oldest to
1770 * newest, relative to the page token offset.
1771 * @returns A promise that resolves with the current batch of downloaded
1772 * tenants and the next page token if available. For the last page, an empty list of tenants
1773 * and no page token are returned.
1774 */
1775 AuthRequestHandler.prototype.listTenants = function (maxResults, pageToken) {
1776 if (maxResults === void 0) { maxResults = MAX_LIST_TENANT_PAGE_SIZE; }
1777 var request = {
1778 pageSize: maxResults,
1779 pageToken: pageToken,
1780 };
1781 // Remove next page token if not provided.
1782 if (typeof request.pageToken === 'undefined') {
1783 delete request.pageToken;
1784 }
1785 return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, LIST_TENANTS, request)
1786 .then(function (response) {
1787 if (!response.tenants) {
1788 response.tenants = [];
1789 delete response.nextPageToken;
1790 }
1791 return response;
1792 });
1793 };
1794 /**
1795 * Deletes a tenant identified by a tenantId.
1796 *
1797 * @param tenantId - The identifier of the tenant to delete.
1798 * @returns A promise that resolves when the tenant is deleted.
1799 */
1800 AuthRequestHandler.prototype.deleteTenant = function (tenantId) {
1801 if (!validator.isNonEmptyString(tenantId)) {
1802 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
1803 }
1804 return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, DELETE_TENANT, {}, { tenantId: tenantId })
1805 .then(function () {
1806 // Return nothing.
1807 });
1808 };
1809 /**
1810 * Creates a new tenant with the properties provided.
1811 *
1812 * @param tenantOptions - The properties to set on the new tenant to be created.
1813 * @returns A promise that resolves with the newly created tenant object.
1814 */
1815 AuthRequestHandler.prototype.createTenant = function (tenantOptions) {
1816 try {
1817 // Construct backend request.
1818 var request = tenant_1.Tenant.buildServerRequest(tenantOptions, true);
1819 return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, CREATE_TENANT, request)
1820 .then(function (response) {
1821 return response;
1822 });
1823 }
1824 catch (e) {
1825 return Promise.reject(e);
1826 }
1827 };
1828 /**
1829 * Updates an existing tenant with the properties provided.
1830 *
1831 * @param tenantId - The tenant identifier of the tenant to update.
1832 * @param tenantOptions - The properties to update on the existing tenant.
1833 * @returns A promise that resolves with the modified tenant object.
1834 */
1835 AuthRequestHandler.prototype.updateTenant = function (tenantId, tenantOptions) {
1836 if (!validator.isNonEmptyString(tenantId)) {
1837 return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
1838 }
1839 try {
1840 // Construct backend request.
1841 var request = tenant_1.Tenant.buildServerRequest(tenantOptions, false);
1842 // Do not traverse deep into testPhoneNumbers. The entire content should be replaced
1843 // and not just specific phone numbers.
1844 var updateMask = utils.generateUpdateMask(request, ['testPhoneNumbers']);
1845 return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, UPDATE_TENANT, request, { tenantId: tenantId, updateMask: updateMask.join(',') })
1846 .then(function (response) {
1847 return response;
1848 });
1849 }
1850 catch (e) {
1851 return Promise.reject(e);
1852 }
1853 };
1854 return AuthRequestHandler;
1855}(AbstractAuthRequestHandler));
1856exports.AuthRequestHandler = AuthRequestHandler;
1857/**
1858 * Utility for sending requests to Auth server that are tenant Auth instance related. This includes user
1859 * management related APIs for specified tenants.
1860 * This extends the BaseFirebaseAuthRequestHandler class.
1861 */
1862var TenantAwareAuthRequestHandler = /** @class */ (function (_super) {
1863 __extends(TenantAwareAuthRequestHandler, _super);
1864 /**
1865 * The FirebaseTenantRequestHandler constructor used to initialize an instance using a
1866 * FirebaseApp and a tenant ID.
1867 *
1868 * @param app - The app used to fetch access tokens to sign API requests.
1869 * @param tenantId - The request handler's tenant ID.
1870 * @constructor
1871 */
1872 function TenantAwareAuthRequestHandler(app, tenantId) {
1873 var _this = _super.call(this, app) || this;
1874 _this.tenantId = tenantId;
1875 return _this;
1876 }
1877 /**
1878 * @returns A new Auth user management resource URL builder instance.
1879 */
1880 TenantAwareAuthRequestHandler.prototype.newAuthUrlBuilder = function () {
1881 return new TenantAwareAuthResourceUrlBuilder(this.app, 'v1', this.tenantId);
1882 };
1883 /**
1884 * @returns A new project config resource URL builder instance.
1885 */
1886 TenantAwareAuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
1887 return new TenantAwareAuthResourceUrlBuilder(this.app, 'v2', this.tenantId);
1888 };
1889 /**
1890 * Imports the list of users provided to Firebase Auth. This is useful when
1891 * migrating from an external authentication system without having to use the Firebase CLI SDK.
1892 * At most, 1000 users are allowed to be imported one at a time.
1893 * When importing a list of password users, UserImportOptions are required to be specified.
1894 *
1895 * Overrides the superclass methods by adding an additional check to match tenant IDs of
1896 * imported user records if present.
1897 *
1898 * @param users - The list of user records to import to Firebase Auth.
1899 * @param options - The user import options, required when the users provided
1900 * include password credentials.
1901 * @returns A promise that resolves when the operation completes
1902 * with the result of the import. This includes the number of successful imports, the number
1903 * of failed uploads and their corresponding errors.
1904 */
1905 TenantAwareAuthRequestHandler.prototype.uploadAccount = function (users, options) {
1906 var _this = this;
1907 // Add additional check to match tenant ID of imported user records.
1908 users.forEach(function (user, index) {
1909 if (validator.isNonEmptyString(user.tenantId) &&
1910 user.tenantId !== _this.tenantId) {
1911 throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISMATCHING_TENANT_ID, "UserRecord of index \"" + index + "\" has mismatching tenant ID \"" + user.tenantId + "\"");
1912 }
1913 });
1914 return _super.prototype.uploadAccount.call(this, users, options);
1915 };
1916 return TenantAwareAuthRequestHandler;
1917}(AbstractAuthRequestHandler));
1918exports.TenantAwareAuthRequestHandler = TenantAwareAuthRequestHandler;
1919function emulatorHost() {
1920 return process.env.FIREBASE_AUTH_EMULATOR_HOST;
1921}
1922/**
1923 * When true the SDK should communicate with the Auth Emulator for all API
1924 * calls and also produce unsigned tokens.
1925 */
1926function useEmulator() {
1927 return !!emulatorHost();
1928}
1929exports.useEmulator = useEmulator;