firebase-admin 9.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +90 -0
- package/lib/app-check/app-check-api-client-internal.js +197 -0
- package/lib/app-check/app-check.js +79 -0
- package/lib/app-check/index.d.ts +160 -0
- package/lib/app-check/index.js +19 -0
- package/lib/app-check/token-generator.js +161 -0
- package/lib/app-check/token-verifier.js +152 -0
- package/lib/auth/action-code-settings-builder.js +118 -0
- package/lib/auth/auth-api-request.js +1856 -0
- package/lib/auth/auth-config.js +636 -0
- package/lib/auth/auth.js +836 -0
- package/lib/auth/identifier.js +40 -0
- package/lib/auth/index.d.ts +1927 -0
- package/lib/auth/index.js +18 -0
- package/lib/auth/tenant-manager.js +140 -0
- package/lib/auth/tenant.js +171 -0
- package/lib/auth/token-generator.js +200 -0
- package/lib/auth/token-verifier.js +259 -0
- package/lib/auth/user-import-builder.js +387 -0
- package/lib/auth/user-record.js +346 -0
- package/lib/credential/credential-internal.js +391 -0
- package/lib/credential/credential.js +44 -0
- package/lib/credential/index.d.ts +169 -0
- package/lib/credential/index.js +23 -0
- package/lib/database/database-internal.js +266 -0
- package/lib/database/index.d.ts +89 -0
- package/lib/database/index.js +31 -0
- package/lib/default-namespace.js +31 -0
- package/lib/firebase-app.js +349 -0
- package/lib/firebase-namespace-api.d.ts +243 -0
- package/lib/firebase-namespace-api.js +18 -0
- package/lib/firebase-namespace.d.ts +31 -0
- package/lib/firebase-namespace.js +417 -0
- package/lib/firestore/firestore-internal.js +105 -0
- package/lib/firestore/index.d.ts +50 -0
- package/lib/firestore/index.js +47 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.js +27 -0
- package/lib/installations/index.d.ts +81 -0
- package/lib/installations/index.js +18 -0
- package/lib/installations/installations-request-handler.js +117 -0
- package/lib/installations/installations.js +62 -0
- package/lib/instance-id/index.d.ts +83 -0
- package/lib/instance-id/index.js +18 -0
- package/lib/instance-id/instance-id.js +87 -0
- package/lib/machine-learning/index.d.ts +249 -0
- package/lib/machine-learning/index.js +18 -0
- package/lib/machine-learning/machine-learning-api-client.js +304 -0
- package/lib/machine-learning/machine-learning-utils.js +62 -0
- package/lib/machine-learning/machine-learning.js +364 -0
- package/lib/messaging/batch-request-internal.js +129 -0
- package/lib/messaging/index.d.ts +1174 -0
- package/lib/messaging/index.js +18 -0
- package/lib/messaging/messaging-api-request-internal.js +128 -0
- package/lib/messaging/messaging-errors-internal.js +106 -0
- package/lib/messaging/messaging-internal.js +484 -0
- package/lib/messaging/messaging.js +846 -0
- package/lib/project-management/android-app.js +176 -0
- package/lib/project-management/index.d.ts +363 -0
- package/lib/project-management/index.js +41 -0
- package/lib/project-management/ios-app.js +88 -0
- package/lib/project-management/project-management-api-request-internal.js +273 -0
- package/lib/project-management/project-management.js +254 -0
- package/lib/remote-config/index.d.ts +369 -0
- package/lib/remote-config/index.js +18 -0
- package/lib/remote-config/remote-config-api-client-internal.js +407 -0
- package/lib/remote-config/remote-config.js +304 -0
- package/lib/security-rules/index.d.ts +216 -0
- package/lib/security-rules/index.js +18 -0
- package/lib/security-rules/security-rules-api-client-internal.js +237 -0
- package/lib/security-rules/security-rules-internal.js +41 -0
- package/lib/security-rules/security-rules.js +310 -0
- package/lib/storage/index.d.ts +60 -0
- package/lib/storage/index.js +18 -0
- package/lib/storage/storage.js +123 -0
- package/lib/utils/api-request.js +845 -0
- package/lib/utils/crypto-signer.js +237 -0
- package/lib/utils/deep-copy.js +78 -0
- package/lib/utils/error.js +1063 -0
- package/lib/utils/index.js +217 -0
- package/lib/utils/jwt.js +355 -0
- package/lib/utils/validator.js +271 -0
- package/package.json +122 -0
|
@@ -0,0 +1,1856 @@
|
|
|
1
|
+
/*! firebase-admin v9.12.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
|
+
*/
|
|
19
|
+
var __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
|
+
})();
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.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;
|
|
34
|
+
var validator = require("../utils/validator");
|
|
35
|
+
var deep_copy_1 = require("../utils/deep-copy");
|
|
36
|
+
var identifier_1 = require("./identifier");
|
|
37
|
+
var error_1 = require("../utils/error");
|
|
38
|
+
var api_request_1 = require("../utils/api-request");
|
|
39
|
+
var user_import_builder_1 = require("./user-import-builder");
|
|
40
|
+
var utils = require("../utils/index");
|
|
41
|
+
var action_code_settings_builder_1 = require("./action-code-settings-builder");
|
|
42
|
+
var auth_config_1 = require("./auth-config");
|
|
43
|
+
var tenant_1 = require("./tenant");
|
|
44
|
+
/** Firebase Auth request header. */
|
|
45
|
+
var FIREBASE_AUTH_HEADER = {
|
|
46
|
+
'X-Client-Version': "Node/Admin/" + utils.getSdkVersion(),
|
|
47
|
+
};
|
|
48
|
+
/** Firebase Auth request timeout duration in milliseconds. */
|
|
49
|
+
var FIREBASE_AUTH_TIMEOUT = 25000;
|
|
50
|
+
/** List of reserved claims which cannot be provided when creating a custom token. */
|
|
51
|
+
exports.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. */
|
|
56
|
+
exports.EMAIL_ACTION_REQUEST_TYPES = [
|
|
57
|
+
'PASSWORD_RESET', 'VERIFY_EMAIL', 'EMAIL_SIGNIN',
|
|
58
|
+
];
|
|
59
|
+
/** Maximum allowed number of characters in the custom claims payload. */
|
|
60
|
+
var MAX_CLAIMS_PAYLOAD_SIZE = 1000;
|
|
61
|
+
/** Maximum allowed number of users to batch download at one time. */
|
|
62
|
+
var MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE = 1000;
|
|
63
|
+
/** Maximum allowed number of users to batch upload at one time. */
|
|
64
|
+
var MAX_UPLOAD_ACCOUNT_BATCH_SIZE = 1000;
|
|
65
|
+
/** Maximum allowed number of users to batch get at one time. */
|
|
66
|
+
var MAX_GET_ACCOUNTS_BATCH_SIZE = 100;
|
|
67
|
+
/** Maximum allowed number of users to batch delete at one time. */
|
|
68
|
+
var MAX_DELETE_ACCOUNTS_BATCH_SIZE = 1000;
|
|
69
|
+
/** Minimum allowed session cookie duration in seconds (5 minutes). */
|
|
70
|
+
var MIN_SESSION_COOKIE_DURATION_SECS = 5 * 60;
|
|
71
|
+
/** Maximum allowed session cookie duration in seconds (2 weeks). */
|
|
72
|
+
var MAX_SESSION_COOKIE_DURATION_SECS = 14 * 24 * 60 * 60;
|
|
73
|
+
/** Maximum allowed number of provider configurations to batch download at one time. */
|
|
74
|
+
var MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE = 100;
|
|
75
|
+
/** The Firebase Auth backend base URL format. */
|
|
76
|
+
var FIREBASE_AUTH_BASE_URL_FORMAT = 'https://identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
|
|
77
|
+
/** Firebase Auth base URlLformat when using the auth emultor. */
|
|
78
|
+
var 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. */
|
|
80
|
+
var 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. */
|
|
82
|
+
var 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. */
|
|
84
|
+
var MAX_LIST_TENANT_PAGE_SIZE = 1000;
|
|
85
|
+
/**
|
|
86
|
+
* Enum for the user write operation type.
|
|
87
|
+
*/
|
|
88
|
+
var 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. */
|
|
95
|
+
var AuthResourceUrlBuilder = /** @class */ (function () {
|
|
96
|
+
/**
|
|
97
|
+
* The resource URL builder constructor.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} projectId The resource project ID.
|
|
100
|
+
* @param {string} 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 {string=} api The backend API name.
|
|
120
|
+
* @param {object=} params The optional additional parameters to substitute in the
|
|
121
|
+
* URL path.
|
|
122
|
+
* @return {Promise<string>} 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. */
|
|
157
|
+
var TenantAwareAuthResourceUrlBuilder = /** @class */ (function (_super) {
|
|
158
|
+
__extends(TenantAwareAuthResourceUrlBuilder, _super);
|
|
159
|
+
/**
|
|
160
|
+
* The tenant aware resource URL builder constructor.
|
|
161
|
+
*
|
|
162
|
+
* @param {string} projectId The resource project ID.
|
|
163
|
+
* @param {string} version The endpoint API version.
|
|
164
|
+
* @param {string} 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 {string=} api The backend API name.
|
|
186
|
+
* @param {object=} params The optional additional parameters to substitute in the
|
|
187
|
+
* URL path.
|
|
188
|
+
* @return {Promise<string>} 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
|
+
*/
|
|
203
|
+
var 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
|
+
*/
|
|
223
|
+
function 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 {any} request The providerUserInfo request object.
|
|
273
|
+
*/
|
|
274
|
+
function 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
|
+
*/
|
|
320
|
+
function 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
|
+
/** Instantiates the createSessionCookie endpoint settings. */
|
|
509
|
+
exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE = new api_request_1.ApiSettings(':createSessionCookie', 'POST')
|
|
510
|
+
// Set request validator.
|
|
511
|
+
.setRequestValidator(function (request) {
|
|
512
|
+
// Validate the ID token is a non-empty string.
|
|
513
|
+
if (!validator.isNonEmptyString(request.idToken)) {
|
|
514
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ID_TOKEN);
|
|
515
|
+
}
|
|
516
|
+
// Validate the custom session cookie duration.
|
|
517
|
+
if (!validator.isNumber(request.validDuration) ||
|
|
518
|
+
request.validDuration < MIN_SESSION_COOKIE_DURATION_SECS ||
|
|
519
|
+
request.validDuration > MAX_SESSION_COOKIE_DURATION_SECS) {
|
|
520
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
|
|
521
|
+
}
|
|
522
|
+
})
|
|
523
|
+
// Set response validator.
|
|
524
|
+
.setResponseValidator(function (response) {
|
|
525
|
+
// Response should always contain the session cookie.
|
|
526
|
+
if (!validator.isNonEmptyString(response.sessionCookie)) {
|
|
527
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
/** Instantiates the uploadAccount endpoint settings. */
|
|
531
|
+
exports.FIREBASE_AUTH_UPLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchCreate', 'POST');
|
|
532
|
+
/** Instantiates the downloadAccount endpoint settings. */
|
|
533
|
+
exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchGet', 'GET')
|
|
534
|
+
// Set request validator.
|
|
535
|
+
.setRequestValidator(function (request) {
|
|
536
|
+
// Validate next page token.
|
|
537
|
+
if (typeof request.nextPageToken !== 'undefined' &&
|
|
538
|
+
!validator.isNonEmptyString(request.nextPageToken)) {
|
|
539
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
|
540
|
+
}
|
|
541
|
+
// Validate max results.
|
|
542
|
+
if (!validator.isNumber(request.maxResults) ||
|
|
543
|
+
request.maxResults <= 0 ||
|
|
544
|
+
request.maxResults > MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE) {
|
|
545
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
|
|
546
|
+
(MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE + "."));
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
/** Instantiates the getAccountInfo endpoint settings. */
|
|
550
|
+
exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
|
|
551
|
+
// Set request validator.
|
|
552
|
+
.setRequestValidator(function (request) {
|
|
553
|
+
if (!request.localId && !request.email && !request.phoneNumber && !request.federatedUserId) {
|
|
554
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
|
555
|
+
}
|
|
556
|
+
})
|
|
557
|
+
// Set response validator.
|
|
558
|
+
.setResponseValidator(function (response) {
|
|
559
|
+
if (!response.users || !response.users.length) {
|
|
560
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
/**
|
|
564
|
+
* Instantiates the getAccountInfo endpoint settings for use when fetching info
|
|
565
|
+
* for multiple accounts.
|
|
566
|
+
*/
|
|
567
|
+
exports.FIREBASE_AUTH_GET_ACCOUNTS_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
|
|
568
|
+
// Set request validator.
|
|
569
|
+
.setRequestValidator(function (request) {
|
|
570
|
+
if (!request.localId && !request.email && !request.phoneNumber && !request.federatedUserId) {
|
|
571
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
/** Instantiates the deleteAccount endpoint settings. */
|
|
575
|
+
exports.FIREBASE_AUTH_DELETE_ACCOUNT = new api_request_1.ApiSettings('/accounts:delete', 'POST')
|
|
576
|
+
// Set request validator.
|
|
577
|
+
.setRequestValidator(function (request) {
|
|
578
|
+
if (!request.localId) {
|
|
579
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
exports.FIREBASE_AUTH_BATCH_DELETE_ACCOUNTS = new api_request_1.ApiSettings('/accounts:batchDelete', 'POST')
|
|
583
|
+
.setRequestValidator(function (request) {
|
|
584
|
+
if (!request.localIds) {
|
|
585
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifiers');
|
|
586
|
+
}
|
|
587
|
+
if (typeof request.force === 'undefined' || request.force !== true) {
|
|
588
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing force=true field');
|
|
589
|
+
}
|
|
590
|
+
})
|
|
591
|
+
.setResponseValidator(function (response) {
|
|
592
|
+
var errors = response.errors || [];
|
|
593
|
+
errors.forEach(function (batchDeleteErrorInfo) {
|
|
594
|
+
if (typeof batchDeleteErrorInfo.index === 'undefined') {
|
|
595
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server BatchDeleteAccountResponse is missing an errors.index field');
|
|
596
|
+
}
|
|
597
|
+
if (!batchDeleteErrorInfo.localId) {
|
|
598
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server BatchDeleteAccountResponse is missing an errors.localId field');
|
|
599
|
+
}
|
|
600
|
+
// Allow the (error) message to be missing/undef.
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
/** Instantiates the setAccountInfo endpoint settings for updating existing accounts. */
|
|
604
|
+
exports.FIREBASE_AUTH_SET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:update', 'POST')
|
|
605
|
+
// Set request validator.
|
|
606
|
+
.setRequestValidator(function (request) {
|
|
607
|
+
// localId is a required parameter.
|
|
608
|
+
if (typeof request.localId === 'undefined') {
|
|
609
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
|
|
610
|
+
}
|
|
611
|
+
// Throw error when tenantId is passed in POST body.
|
|
612
|
+
if (typeof request.tenantId !== 'undefined') {
|
|
613
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "UpdateRequest" property.');
|
|
614
|
+
}
|
|
615
|
+
validateCreateEditRequest(request, WriteOperationType.Update);
|
|
616
|
+
})
|
|
617
|
+
// Set response validator.
|
|
618
|
+
.setResponseValidator(function (response) {
|
|
619
|
+
// If the localId is not returned, then the request failed.
|
|
620
|
+
if (!response.localId) {
|
|
621
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
/**
|
|
625
|
+
* Instantiates the signupNewUser endpoint settings for creating a new user with or without
|
|
626
|
+
* uid being specified. The backend will create a new one if not provided and return it.
|
|
627
|
+
*/
|
|
628
|
+
exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = new api_request_1.ApiSettings('/accounts', 'POST')
|
|
629
|
+
// Set request validator.
|
|
630
|
+
.setRequestValidator(function (request) {
|
|
631
|
+
// signupNewUser does not support customAttributes.
|
|
632
|
+
if (typeof request.customAttributes !== 'undefined') {
|
|
633
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"customAttributes" cannot be set when creating a new user.');
|
|
634
|
+
}
|
|
635
|
+
// signupNewUser does not support validSince.
|
|
636
|
+
if (typeof request.validSince !== 'undefined') {
|
|
637
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"validSince" cannot be set when creating a new user.');
|
|
638
|
+
}
|
|
639
|
+
// Throw error when tenantId is passed in POST body.
|
|
640
|
+
if (typeof request.tenantId !== 'undefined') {
|
|
641
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"tenantId" is an invalid "CreateRequest" property.');
|
|
642
|
+
}
|
|
643
|
+
validateCreateEditRequest(request, WriteOperationType.Create);
|
|
644
|
+
})
|
|
645
|
+
// Set response validator.
|
|
646
|
+
.setResponseValidator(function (response) {
|
|
647
|
+
// If the localId is not returned, then the request failed.
|
|
648
|
+
if (!response.localId) {
|
|
649
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new user');
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
var FIREBASE_AUTH_GET_OOB_CODE = new api_request_1.ApiSettings('/accounts:sendOobCode', 'POST')
|
|
653
|
+
// Set request validator.
|
|
654
|
+
.setRequestValidator(function (request) {
|
|
655
|
+
if (!validator.isEmail(request.email)) {
|
|
656
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
|
|
657
|
+
}
|
|
658
|
+
if (exports.EMAIL_ACTION_REQUEST_TYPES.indexOf(request.requestType) === -1) {
|
|
659
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"" + request.requestType + "\" is not a supported email action request type.");
|
|
660
|
+
}
|
|
661
|
+
})
|
|
662
|
+
// Set response validator.
|
|
663
|
+
.setResponseValidator(function (response) {
|
|
664
|
+
// If the oobLink is not returned, then the request failed.
|
|
665
|
+
if (!response.oobLink) {
|
|
666
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create the email action link');
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
/** Instantiates the retrieve OIDC configuration endpoint settings. */
|
|
670
|
+
var GET_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'GET')
|
|
671
|
+
// Set response validator.
|
|
672
|
+
.setResponseValidator(function (response) {
|
|
673
|
+
// Response should always contain the OIDC provider resource name.
|
|
674
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
675
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get OIDC configuration');
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
/** Instantiates the delete OIDC configuration endpoint settings. */
|
|
679
|
+
var DELETE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}', 'DELETE');
|
|
680
|
+
/** Instantiates the create OIDC configuration endpoint settings. */
|
|
681
|
+
var CREATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs?oauthIdpConfigId={providerId}', 'POST')
|
|
682
|
+
// Set response validator.
|
|
683
|
+
.setResponseValidator(function (response) {
|
|
684
|
+
// Response should always contain the OIDC provider resource name.
|
|
685
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
686
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC configuration');
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
/** Instantiates the update OIDC configuration endpoint settings. */
|
|
690
|
+
var UPDATE_OAUTH_IDP_CONFIG = new api_request_1.ApiSettings('/oauthIdpConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
|
|
691
|
+
// Set response validator.
|
|
692
|
+
.setResponseValidator(function (response) {
|
|
693
|
+
// Response should always contain the configuration resource name.
|
|
694
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
695
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC configuration');
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
/** Instantiates the list OIDC configuration endpoint settings. */
|
|
699
|
+
var LIST_OAUTH_IDP_CONFIGS = new api_request_1.ApiSettings('/oauthIdpConfigs', 'GET')
|
|
700
|
+
// Set request validator.
|
|
701
|
+
.setRequestValidator(function (request) {
|
|
702
|
+
// Validate next page token.
|
|
703
|
+
if (typeof request.pageToken !== 'undefined' &&
|
|
704
|
+
!validator.isNonEmptyString(request.pageToken)) {
|
|
705
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
|
706
|
+
}
|
|
707
|
+
// Validate max results.
|
|
708
|
+
if (!validator.isNumber(request.pageSize) ||
|
|
709
|
+
request.pageSize <= 0 ||
|
|
710
|
+
request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
|
|
711
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
|
|
712
|
+
(MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
/** Instantiates the retrieve SAML configuration endpoint settings. */
|
|
716
|
+
var GET_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'GET')
|
|
717
|
+
// Set response validator.
|
|
718
|
+
.setResponseValidator(function (response) {
|
|
719
|
+
// Response should always contain the SAML provider resource name.
|
|
720
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
721
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get SAML configuration');
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
/** Instantiates the delete SAML configuration endpoint settings. */
|
|
725
|
+
var DELETE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}', 'DELETE');
|
|
726
|
+
/** Instantiates the create SAML configuration endpoint settings. */
|
|
727
|
+
var CREATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs?inboundSamlConfigId={providerId}', 'POST')
|
|
728
|
+
// Set response validator.
|
|
729
|
+
.setResponseValidator(function (response) {
|
|
730
|
+
// Response should always contain the SAML provider resource name.
|
|
731
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
732
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML configuration');
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
/** Instantiates the update SAML configuration endpoint settings. */
|
|
736
|
+
var UPDATE_INBOUND_SAML_CONFIG = new api_request_1.ApiSettings('/inboundSamlConfigs/{providerId}?updateMask={updateMask}', 'PATCH')
|
|
737
|
+
// Set response validator.
|
|
738
|
+
.setResponseValidator(function (response) {
|
|
739
|
+
// Response should always contain the configuration resource name.
|
|
740
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
741
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML configuration');
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
/** Instantiates the list SAML configuration endpoint settings. */
|
|
745
|
+
var LIST_INBOUND_SAML_CONFIGS = new api_request_1.ApiSettings('/inboundSamlConfigs', 'GET')
|
|
746
|
+
// Set request validator.
|
|
747
|
+
.setRequestValidator(function (request) {
|
|
748
|
+
// Validate next page token.
|
|
749
|
+
if (typeof request.pageToken !== 'undefined' &&
|
|
750
|
+
!validator.isNonEmptyString(request.pageToken)) {
|
|
751
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
|
752
|
+
}
|
|
753
|
+
// Validate max results.
|
|
754
|
+
if (!validator.isNumber(request.pageSize) ||
|
|
755
|
+
request.pageSize <= 0 ||
|
|
756
|
+
request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
|
|
757
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
|
|
758
|
+
(MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
/**
|
|
762
|
+
* Class that provides the mechanism to send requests to the Firebase Auth backend endpoints.
|
|
763
|
+
*/
|
|
764
|
+
var AbstractAuthRequestHandler = /** @class */ (function () {
|
|
765
|
+
/**
|
|
766
|
+
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
|
767
|
+
* @constructor
|
|
768
|
+
*/
|
|
769
|
+
function AbstractAuthRequestHandler(app) {
|
|
770
|
+
this.app = app;
|
|
771
|
+
if (typeof app !== 'object' || app === null || !('options' in app)) {
|
|
772
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.auth() must be a valid Firebase app instance.');
|
|
773
|
+
}
|
|
774
|
+
this.httpClient = new AuthHttpClient(app);
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* @param {any} response The response to check for errors.
|
|
778
|
+
* @return {string|null} The error code if present; null otherwise.
|
|
779
|
+
*/
|
|
780
|
+
AbstractAuthRequestHandler.getErrorCode = function (response) {
|
|
781
|
+
return (validator.isNonNullObject(response) && response.error && response.error.message) || null;
|
|
782
|
+
};
|
|
783
|
+
AbstractAuthRequestHandler.addUidToRequest = function (id, request) {
|
|
784
|
+
if (!validator.isUid(id.uid)) {
|
|
785
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
|
|
786
|
+
}
|
|
787
|
+
request.localId ? request.localId.push(id.uid) : request.localId = [id.uid];
|
|
788
|
+
return request;
|
|
789
|
+
};
|
|
790
|
+
AbstractAuthRequestHandler.addEmailToRequest = function (id, request) {
|
|
791
|
+
if (!validator.isEmail(id.email)) {
|
|
792
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
|
|
793
|
+
}
|
|
794
|
+
request.email ? request.email.push(id.email) : request.email = [id.email];
|
|
795
|
+
return request;
|
|
796
|
+
};
|
|
797
|
+
AbstractAuthRequestHandler.addPhoneToRequest = function (id, request) {
|
|
798
|
+
if (!validator.isPhoneNumber(id.phoneNumber)) {
|
|
799
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER);
|
|
800
|
+
}
|
|
801
|
+
request.phoneNumber ? request.phoneNumber.push(id.phoneNumber) : request.phoneNumber = [id.phoneNumber];
|
|
802
|
+
return request;
|
|
803
|
+
};
|
|
804
|
+
AbstractAuthRequestHandler.addProviderToRequest = function (id, request) {
|
|
805
|
+
if (!validator.isNonEmptyString(id.providerId)) {
|
|
806
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
|
|
807
|
+
}
|
|
808
|
+
if (!validator.isNonEmptyString(id.providerUid)) {
|
|
809
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_UID);
|
|
810
|
+
}
|
|
811
|
+
var federatedUserId = {
|
|
812
|
+
providerId: id.providerId,
|
|
813
|
+
rawId: id.providerUid,
|
|
814
|
+
};
|
|
815
|
+
request.federatedUserId
|
|
816
|
+
? request.federatedUserId.push(federatedUserId)
|
|
817
|
+
: request.federatedUserId = [federatedUserId];
|
|
818
|
+
return request;
|
|
819
|
+
};
|
|
820
|
+
/**
|
|
821
|
+
* Creates a new Firebase session cookie with the specified duration that can be used for
|
|
822
|
+
* session management (set as a server side session cookie with custom cookie policy).
|
|
823
|
+
* The session cookie JWT will have the same payload claims as the provided ID token.
|
|
824
|
+
*
|
|
825
|
+
* @param {string} idToken The Firebase ID token to exchange for a session cookie.
|
|
826
|
+
* @param {number} expiresIn The session cookie duration in milliseconds.
|
|
827
|
+
*
|
|
828
|
+
* @return {Promise<string>} A promise that resolves on success with the created session cookie.
|
|
829
|
+
*/
|
|
830
|
+
AbstractAuthRequestHandler.prototype.createSessionCookie = function (idToken, expiresIn) {
|
|
831
|
+
var request = {
|
|
832
|
+
idToken: idToken,
|
|
833
|
+
// Convert to seconds.
|
|
834
|
+
validDuration: expiresIn / 1000,
|
|
835
|
+
};
|
|
836
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE, request)
|
|
837
|
+
.then(function (response) { return response.sessionCookie; });
|
|
838
|
+
};
|
|
839
|
+
/**
|
|
840
|
+
* Looks up a user by uid.
|
|
841
|
+
*
|
|
842
|
+
* @param {string} uid The uid of the user to lookup.
|
|
843
|
+
* @return {Promise<object>} A promise that resolves with the user information.
|
|
844
|
+
*/
|
|
845
|
+
AbstractAuthRequestHandler.prototype.getAccountInfoByUid = function (uid) {
|
|
846
|
+
if (!validator.isUid(uid)) {
|
|
847
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
|
848
|
+
}
|
|
849
|
+
var request = {
|
|
850
|
+
localId: [uid],
|
|
851
|
+
};
|
|
852
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
|
853
|
+
};
|
|
854
|
+
/**
|
|
855
|
+
* Looks up a user by email.
|
|
856
|
+
*
|
|
857
|
+
* @param {string} email The email of the user to lookup.
|
|
858
|
+
* @return {Promise<object>} A promise that resolves with the user information.
|
|
859
|
+
*/
|
|
860
|
+
AbstractAuthRequestHandler.prototype.getAccountInfoByEmail = function (email) {
|
|
861
|
+
if (!validator.isEmail(email)) {
|
|
862
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL));
|
|
863
|
+
}
|
|
864
|
+
var request = {
|
|
865
|
+
email: [email],
|
|
866
|
+
};
|
|
867
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
|
868
|
+
};
|
|
869
|
+
/**
|
|
870
|
+
* Looks up a user by phone number.
|
|
871
|
+
*
|
|
872
|
+
* @param {string} phoneNumber The phone number of the user to lookup.
|
|
873
|
+
* @return {Promise<object>} A promise that resolves with the user information.
|
|
874
|
+
*/
|
|
875
|
+
AbstractAuthRequestHandler.prototype.getAccountInfoByPhoneNumber = function (phoneNumber) {
|
|
876
|
+
if (!validator.isPhoneNumber(phoneNumber)) {
|
|
877
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER));
|
|
878
|
+
}
|
|
879
|
+
var request = {
|
|
880
|
+
phoneNumber: [phoneNumber],
|
|
881
|
+
};
|
|
882
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
|
883
|
+
};
|
|
884
|
+
AbstractAuthRequestHandler.prototype.getAccountInfoByFederatedUid = function (providerId, rawId) {
|
|
885
|
+
if (!validator.isNonEmptyString(providerId) || !validator.isNonEmptyString(rawId)) {
|
|
886
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
|
|
887
|
+
}
|
|
888
|
+
var request = {
|
|
889
|
+
federatedUserId: [{
|
|
890
|
+
providerId: providerId,
|
|
891
|
+
rawId: rawId,
|
|
892
|
+
}],
|
|
893
|
+
};
|
|
894
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
|
|
895
|
+
};
|
|
896
|
+
/**
|
|
897
|
+
* Looks up multiple users by their identifiers (uid, email, etc).
|
|
898
|
+
*
|
|
899
|
+
* @param {UserIdentifier[]} identifiers The identifiers indicating the users
|
|
900
|
+
* to be looked up. Must have <= 100 entries.
|
|
901
|
+
* @param {Promise<object>} A promise that resolves with the set of successfully
|
|
902
|
+
* looked up users. Possibly empty if no users were looked up.
|
|
903
|
+
*/
|
|
904
|
+
AbstractAuthRequestHandler.prototype.getAccountInfoByIdentifiers = function (identifiers) {
|
|
905
|
+
if (identifiers.length === 0) {
|
|
906
|
+
return Promise.resolve({ users: [] });
|
|
907
|
+
}
|
|
908
|
+
else if (identifiers.length > MAX_GET_ACCOUNTS_BATCH_SIZE) {
|
|
909
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, '`identifiers` parameter must have <= ' + MAX_GET_ACCOUNTS_BATCH_SIZE + ' entries.');
|
|
910
|
+
}
|
|
911
|
+
var request = {};
|
|
912
|
+
for (var _i = 0, identifiers_1 = identifiers; _i < identifiers_1.length; _i++) {
|
|
913
|
+
var id = identifiers_1[_i];
|
|
914
|
+
if (identifier_1.isUidIdentifier(id)) {
|
|
915
|
+
request = AbstractAuthRequestHandler.addUidToRequest(id, request);
|
|
916
|
+
}
|
|
917
|
+
else if (identifier_1.isEmailIdentifier(id)) {
|
|
918
|
+
request = AbstractAuthRequestHandler.addEmailToRequest(id, request);
|
|
919
|
+
}
|
|
920
|
+
else if (identifier_1.isPhoneIdentifier(id)) {
|
|
921
|
+
request = AbstractAuthRequestHandler.addPhoneToRequest(id, request);
|
|
922
|
+
}
|
|
923
|
+
else if (identifier_1.isProviderIdentifier(id)) {
|
|
924
|
+
request = AbstractAuthRequestHandler.addProviderToRequest(id, request);
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Unrecognized identifier: ' + id);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNTS_INFO, request);
|
|
931
|
+
};
|
|
932
|
+
/**
|
|
933
|
+
* Exports the users (single batch only) with a size of maxResults and starting from
|
|
934
|
+
* the offset as specified by pageToken.
|
|
935
|
+
*
|
|
936
|
+
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
|
|
937
|
+
* allowed limit.
|
|
938
|
+
* @param {string=} pageToken The next page token. If not specified, returns users starting
|
|
939
|
+
* without any offset. Users are returned in the order they were created from oldest to
|
|
940
|
+
* newest, relative to the page token offset.
|
|
941
|
+
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
|
|
942
|
+
* users and the next page token if available. For the last page, an empty list of users
|
|
943
|
+
* and no page token are returned.
|
|
944
|
+
*/
|
|
945
|
+
AbstractAuthRequestHandler.prototype.downloadAccount = function (maxResults, pageToken) {
|
|
946
|
+
if (maxResults === void 0) { maxResults = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE; }
|
|
947
|
+
// Construct request.
|
|
948
|
+
var request = {
|
|
949
|
+
maxResults: maxResults,
|
|
950
|
+
nextPageToken: pageToken,
|
|
951
|
+
};
|
|
952
|
+
// Remove next page token if not provided.
|
|
953
|
+
if (typeof request.nextPageToken === 'undefined') {
|
|
954
|
+
delete request.nextPageToken;
|
|
955
|
+
}
|
|
956
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT, request)
|
|
957
|
+
.then(function (response) {
|
|
958
|
+
// No more users available.
|
|
959
|
+
if (!response.users) {
|
|
960
|
+
response.users = [];
|
|
961
|
+
}
|
|
962
|
+
return response;
|
|
963
|
+
});
|
|
964
|
+
};
|
|
965
|
+
/**
|
|
966
|
+
* Imports the list of users provided to Firebase Auth. This is useful when
|
|
967
|
+
* migrating from an external authentication system without having to use the Firebase CLI SDK.
|
|
968
|
+
* At most, 1000 users are allowed to be imported one at a time.
|
|
969
|
+
* When importing a list of password users, UserImportOptions are required to be specified.
|
|
970
|
+
*
|
|
971
|
+
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
|
|
972
|
+
* @param {UserImportOptions=} options The user import options, required when the users provided
|
|
973
|
+
* include password credentials.
|
|
974
|
+
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
|
|
975
|
+
* with the result of the import. This includes the number of successful imports, the number
|
|
976
|
+
* of failed uploads and their corresponding errors.
|
|
977
|
+
*/
|
|
978
|
+
AbstractAuthRequestHandler.prototype.uploadAccount = function (users, options) {
|
|
979
|
+
// This will throw if any error is detected in the hash options.
|
|
980
|
+
// For errors in the list of users, this will not throw and will report the errors and the
|
|
981
|
+
// corresponding user index in the user import generated response below.
|
|
982
|
+
// No need to validate raw request or raw response as this is done in UserImportBuilder.
|
|
983
|
+
var userImportBuilder = new user_import_builder_1.UserImportBuilder(users, options, function (userRequest) {
|
|
984
|
+
// Pass true to validate the uploadAccount specific fields.
|
|
985
|
+
validateCreateEditRequest(userRequest, WriteOperationType.Upload);
|
|
986
|
+
});
|
|
987
|
+
var request = userImportBuilder.buildRequest();
|
|
988
|
+
// Fail quickly if more users than allowed are to be imported.
|
|
989
|
+
if (validator.isArray(users) && users.length > MAX_UPLOAD_ACCOUNT_BATCH_SIZE) {
|
|
990
|
+
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.");
|
|
991
|
+
}
|
|
992
|
+
// If no remaining user in request after client side processing, there is no need
|
|
993
|
+
// to send the request to the server.
|
|
994
|
+
if (!request.users || request.users.length === 0) {
|
|
995
|
+
return Promise.resolve(userImportBuilder.buildResponse([]));
|
|
996
|
+
}
|
|
997
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_UPLOAD_ACCOUNT, request)
|
|
998
|
+
.then(function (response) {
|
|
999
|
+
// No error object is returned if no error encountered.
|
|
1000
|
+
var failedUploads = (response.error || []);
|
|
1001
|
+
// Rewrite response as UserImportResult and re-insert client previously detected errors.
|
|
1002
|
+
return userImportBuilder.buildResponse(failedUploads);
|
|
1003
|
+
});
|
|
1004
|
+
};
|
|
1005
|
+
/**
|
|
1006
|
+
* Deletes an account identified by a uid.
|
|
1007
|
+
*
|
|
1008
|
+
* @param {string} uid The uid of the user to delete.
|
|
1009
|
+
* @return {Promise<object>} A promise that resolves when the user is deleted.
|
|
1010
|
+
*/
|
|
1011
|
+
AbstractAuthRequestHandler.prototype.deleteAccount = function (uid) {
|
|
1012
|
+
if (!validator.isUid(uid)) {
|
|
1013
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
|
1014
|
+
}
|
|
1015
|
+
var request = {
|
|
1016
|
+
localId: uid,
|
|
1017
|
+
};
|
|
1018
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_DELETE_ACCOUNT, request);
|
|
1019
|
+
};
|
|
1020
|
+
AbstractAuthRequestHandler.prototype.deleteAccounts = function (uids, force) {
|
|
1021
|
+
if (uids.length === 0) {
|
|
1022
|
+
return Promise.resolve({});
|
|
1023
|
+
}
|
|
1024
|
+
else if (uids.length > MAX_DELETE_ACCOUNTS_BATCH_SIZE) {
|
|
1025
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, '`uids` parameter must have <= ' + MAX_DELETE_ACCOUNTS_BATCH_SIZE + ' entries.');
|
|
1026
|
+
}
|
|
1027
|
+
var request = {
|
|
1028
|
+
localIds: [],
|
|
1029
|
+
force: force,
|
|
1030
|
+
};
|
|
1031
|
+
uids.forEach(function (uid) {
|
|
1032
|
+
if (!validator.isUid(uid)) {
|
|
1033
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
|
|
1034
|
+
}
|
|
1035
|
+
request.localIds.push(uid);
|
|
1036
|
+
});
|
|
1037
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_BATCH_DELETE_ACCOUNTS, request);
|
|
1038
|
+
};
|
|
1039
|
+
/**
|
|
1040
|
+
* Sets additional developer claims on an existing user identified by provided UID.
|
|
1041
|
+
*
|
|
1042
|
+
* @param {string} uid The user to edit.
|
|
1043
|
+
* @param {object} customUserClaims The developer claims to set.
|
|
1044
|
+
* @return {Promise<string>} A promise that resolves when the operation completes
|
|
1045
|
+
* with the user id that was edited.
|
|
1046
|
+
*/
|
|
1047
|
+
AbstractAuthRequestHandler.prototype.setCustomUserClaims = function (uid, customUserClaims) {
|
|
1048
|
+
// Validate user UID.
|
|
1049
|
+
if (!validator.isUid(uid)) {
|
|
1050
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
|
1051
|
+
}
|
|
1052
|
+
else if (!validator.isObject(customUserClaims)) {
|
|
1053
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'CustomUserClaims argument must be an object or null.'));
|
|
1054
|
+
}
|
|
1055
|
+
// Delete operation. Replace null with an empty object.
|
|
1056
|
+
if (customUserClaims === null) {
|
|
1057
|
+
customUserClaims = {};
|
|
1058
|
+
}
|
|
1059
|
+
// Construct custom user attribute editting request.
|
|
1060
|
+
var request = {
|
|
1061
|
+
localId: uid,
|
|
1062
|
+
customAttributes: JSON.stringify(customUserClaims),
|
|
1063
|
+
};
|
|
1064
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
|
1065
|
+
.then(function (response) {
|
|
1066
|
+
return response.localId;
|
|
1067
|
+
});
|
|
1068
|
+
};
|
|
1069
|
+
/**
|
|
1070
|
+
* Edits an existing user.
|
|
1071
|
+
*
|
|
1072
|
+
* @param {string} uid The user to edit.
|
|
1073
|
+
* @param {object} properties The properties to set on the user.
|
|
1074
|
+
* @return {Promise<string>} A promise that resolves when the operation completes
|
|
1075
|
+
* with the user id that was edited.
|
|
1076
|
+
*/
|
|
1077
|
+
AbstractAuthRequestHandler.prototype.updateExistingAccount = function (uid, properties) {
|
|
1078
|
+
if (!validator.isUid(uid)) {
|
|
1079
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
|
1080
|
+
}
|
|
1081
|
+
else if (!validator.isNonNullObject(properties)) {
|
|
1082
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
|
|
1083
|
+
}
|
|
1084
|
+
else if (validator.isNonNullObject(properties.providerToLink)) {
|
|
1085
|
+
// TODO(rsgowman): These checks overlap somewhat with
|
|
1086
|
+
// validateProviderUserInfo. It may be possible to refactor a bit.
|
|
1087
|
+
if (!validator.isNonEmptyString(properties.providerToLink.providerId)) {
|
|
1088
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.providerId of properties argument must be a non-empty string.');
|
|
1089
|
+
}
|
|
1090
|
+
if (!validator.isNonEmptyString(properties.providerToLink.uid)) {
|
|
1091
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.uid of properties argument must be a non-empty string.');
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
else if (typeof properties.providersToUnlink !== 'undefined') {
|
|
1095
|
+
if (!validator.isArray(properties.providersToUnlink)) {
|
|
1096
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
|
|
1097
|
+
}
|
|
1098
|
+
properties.providersToUnlink.forEach(function (providerId) {
|
|
1099
|
+
if (!validator.isNonEmptyString(providerId)) {
|
|
1100
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
// Build the setAccountInfo request.
|
|
1105
|
+
var request = deep_copy_1.deepCopy(properties);
|
|
1106
|
+
request.localId = uid;
|
|
1107
|
+
// For deleting displayName or photoURL, these values must be passed as null.
|
|
1108
|
+
// They will be removed from the backend request and an additional parameter
|
|
1109
|
+
// deleteAttribute: ['PHOTO_URL', 'DISPLAY_NAME']
|
|
1110
|
+
// with an array of the parameter names to delete will be passed.
|
|
1111
|
+
// Parameters that are deletable and their deleteAttribute names.
|
|
1112
|
+
// Use client facing names, photoURL instead of photoUrl.
|
|
1113
|
+
var deletableParams = {
|
|
1114
|
+
displayName: 'DISPLAY_NAME',
|
|
1115
|
+
photoURL: 'PHOTO_URL',
|
|
1116
|
+
};
|
|
1117
|
+
// Properties to delete if available.
|
|
1118
|
+
request.deleteAttribute = [];
|
|
1119
|
+
for (var key in deletableParams) {
|
|
1120
|
+
if (request[key] === null) {
|
|
1121
|
+
// Add property identifier to list of attributes to delete.
|
|
1122
|
+
request.deleteAttribute.push(deletableParams[key]);
|
|
1123
|
+
// Remove property from request.
|
|
1124
|
+
delete request[key];
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
if (request.deleteAttribute.length === 0) {
|
|
1128
|
+
delete request.deleteAttribute;
|
|
1129
|
+
}
|
|
1130
|
+
// For deleting phoneNumber, this value must be passed as null.
|
|
1131
|
+
// It will be removed from the backend request and an additional parameter
|
|
1132
|
+
// deleteProvider: ['phone'] with an array of providerIds (phone in this case),
|
|
1133
|
+
// will be passed.
|
|
1134
|
+
if (request.phoneNumber === null) {
|
|
1135
|
+
request.deleteProvider ? request.deleteProvider.push('phone') : request.deleteProvider = ['phone'];
|
|
1136
|
+
delete request.phoneNumber;
|
|
1137
|
+
}
|
|
1138
|
+
if (typeof (request.providerToLink) !== 'undefined') {
|
|
1139
|
+
request.linkProviderUserInfo = deep_copy_1.deepCopy(request.providerToLink);
|
|
1140
|
+
delete request.providerToLink;
|
|
1141
|
+
request.linkProviderUserInfo.rawId = request.linkProviderUserInfo.uid;
|
|
1142
|
+
delete request.linkProviderUserInfo.uid;
|
|
1143
|
+
}
|
|
1144
|
+
if (typeof (request.providersToUnlink) !== 'undefined') {
|
|
1145
|
+
if (!validator.isArray(request.deleteProvider)) {
|
|
1146
|
+
request.deleteProvider = [];
|
|
1147
|
+
}
|
|
1148
|
+
request.deleteProvider = request.deleteProvider.concat(request.providersToUnlink);
|
|
1149
|
+
delete request.providersToUnlink;
|
|
1150
|
+
}
|
|
1151
|
+
// Rewrite photoURL to photoUrl.
|
|
1152
|
+
if (typeof request.photoURL !== 'undefined') {
|
|
1153
|
+
request.photoUrl = request.photoURL;
|
|
1154
|
+
delete request.photoURL;
|
|
1155
|
+
}
|
|
1156
|
+
// Rewrite disabled to disableUser.
|
|
1157
|
+
if (typeof request.disabled !== 'undefined') {
|
|
1158
|
+
request.disableUser = request.disabled;
|
|
1159
|
+
delete request.disabled;
|
|
1160
|
+
}
|
|
1161
|
+
// Construct mfa related user data.
|
|
1162
|
+
if (validator.isNonNullObject(request.multiFactor)) {
|
|
1163
|
+
if (request.multiFactor.enrolledFactors === null) {
|
|
1164
|
+
// Remove all second factors.
|
|
1165
|
+
request.mfa = {};
|
|
1166
|
+
}
|
|
1167
|
+
else if (validator.isArray(request.multiFactor.enrolledFactors)) {
|
|
1168
|
+
request.mfa = {
|
|
1169
|
+
enrollments: [],
|
|
1170
|
+
};
|
|
1171
|
+
try {
|
|
1172
|
+
request.multiFactor.enrolledFactors.forEach(function (multiFactorInfo) {
|
|
1173
|
+
request.mfa.enrollments.push(user_import_builder_1.convertMultiFactorInfoToServerFormat(multiFactorInfo));
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
catch (e) {
|
|
1177
|
+
return Promise.reject(e);
|
|
1178
|
+
}
|
|
1179
|
+
if (request.mfa.enrollments.length === 0) {
|
|
1180
|
+
delete request.mfa.enrollments;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
delete request.multiFactor;
|
|
1184
|
+
}
|
|
1185
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
|
1186
|
+
.then(function (response) {
|
|
1187
|
+
return response.localId;
|
|
1188
|
+
});
|
|
1189
|
+
};
|
|
1190
|
+
/**
|
|
1191
|
+
* Revokes all refresh tokens for the specified user identified by the uid provided.
|
|
1192
|
+
* In addition to revoking all refresh tokens for a user, all ID tokens issued
|
|
1193
|
+
* before revocation will also be revoked on the Auth backend. Any request with an
|
|
1194
|
+
* ID token generated before revocation will be rejected with a token expired error.
|
|
1195
|
+
* Note that due to the fact that the timestamp is stored in seconds, any tokens minted in
|
|
1196
|
+
* the same second as the revocation will still be valid. If there is a chance that a token
|
|
1197
|
+
* was minted in the last second, delay for 1 second before revoking.
|
|
1198
|
+
*
|
|
1199
|
+
* @param {string} uid The user whose tokens are to be revoked.
|
|
1200
|
+
* @return {Promise<string>} A promise that resolves when the operation completes
|
|
1201
|
+
* successfully with the user id of the corresponding user.
|
|
1202
|
+
*/
|
|
1203
|
+
AbstractAuthRequestHandler.prototype.revokeRefreshTokens = function (uid) {
|
|
1204
|
+
// Validate user UID.
|
|
1205
|
+
if (!validator.isUid(uid)) {
|
|
1206
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
|
|
1207
|
+
}
|
|
1208
|
+
var request = {
|
|
1209
|
+
localId: uid,
|
|
1210
|
+
// validSince is in UTC seconds.
|
|
1211
|
+
validSince: Math.floor(new Date().getTime() / 1000),
|
|
1212
|
+
};
|
|
1213
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
|
|
1214
|
+
.then(function (response) {
|
|
1215
|
+
return response.localId;
|
|
1216
|
+
});
|
|
1217
|
+
};
|
|
1218
|
+
/**
|
|
1219
|
+
* Create a new user with the properties supplied.
|
|
1220
|
+
*
|
|
1221
|
+
* @param {object} properties The properties to set on the user.
|
|
1222
|
+
* @return {Promise<string>} A promise that resolves when the operation completes
|
|
1223
|
+
* with the user id that was created.
|
|
1224
|
+
*/
|
|
1225
|
+
AbstractAuthRequestHandler.prototype.createNewAccount = function (properties) {
|
|
1226
|
+
if (!validator.isNonNullObject(properties)) {
|
|
1227
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
|
|
1228
|
+
}
|
|
1229
|
+
var request = deep_copy_1.deepCopy(properties);
|
|
1230
|
+
// Rewrite photoURL to photoUrl.
|
|
1231
|
+
if (typeof request.photoURL !== 'undefined') {
|
|
1232
|
+
request.photoUrl = request.photoURL;
|
|
1233
|
+
delete request.photoURL;
|
|
1234
|
+
}
|
|
1235
|
+
// Rewrite uid to localId if it exists.
|
|
1236
|
+
if (typeof request.uid !== 'undefined') {
|
|
1237
|
+
request.localId = request.uid;
|
|
1238
|
+
delete request.uid;
|
|
1239
|
+
}
|
|
1240
|
+
// Construct mfa related user data.
|
|
1241
|
+
if (validator.isNonNullObject(request.multiFactor)) {
|
|
1242
|
+
if (validator.isNonEmptyArray(request.multiFactor.enrolledFactors)) {
|
|
1243
|
+
var mfaInfo_1 = [];
|
|
1244
|
+
try {
|
|
1245
|
+
request.multiFactor.enrolledFactors.forEach(function (multiFactorInfo) {
|
|
1246
|
+
// Enrollment time and uid are not allowed for signupNewUser endpoint.
|
|
1247
|
+
// They will automatically be provisioned server side.
|
|
1248
|
+
if ('enrollmentTime' in multiFactorInfo) {
|
|
1249
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"enrollmentTime" is not supported when adding second factors via "createUser()"');
|
|
1250
|
+
}
|
|
1251
|
+
else if ('uid' in multiFactorInfo) {
|
|
1252
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"uid" is not supported when adding second factors via "createUser()"');
|
|
1253
|
+
}
|
|
1254
|
+
mfaInfo_1.push(user_import_builder_1.convertMultiFactorInfoToServerFormat(multiFactorInfo));
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
catch (e) {
|
|
1258
|
+
return Promise.reject(e);
|
|
1259
|
+
}
|
|
1260
|
+
request.mfaInfo = mfaInfo_1;
|
|
1261
|
+
}
|
|
1262
|
+
delete request.multiFactor;
|
|
1263
|
+
}
|
|
1264
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_SIGN_UP_NEW_USER, request)
|
|
1265
|
+
.then(function (response) {
|
|
1266
|
+
// Return the user id.
|
|
1267
|
+
return response.localId;
|
|
1268
|
+
});
|
|
1269
|
+
};
|
|
1270
|
+
/**
|
|
1271
|
+
* Generates the out of band email action link for the email specified using the action code settings provided.
|
|
1272
|
+
* Returns a promise that resolves with the generated link.
|
|
1273
|
+
*
|
|
1274
|
+
* @param {string} requestType The request type. This could be either used for password reset,
|
|
1275
|
+
* email verification, email link sign-in.
|
|
1276
|
+
* @param {string} email The email of the user the link is being sent to.
|
|
1277
|
+
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
|
|
1278
|
+
* the link is to be handled by a mobile app and the additional state information to be passed in the
|
|
1279
|
+
* deep link, etc. Required when requestType == 'EMAIL_SIGNIN'
|
|
1280
|
+
* @return {Promise<string>} A promise that resolves with the email action link.
|
|
1281
|
+
*/
|
|
1282
|
+
AbstractAuthRequestHandler.prototype.getEmailActionLink = function (requestType, email, actionCodeSettings) {
|
|
1283
|
+
var request = { requestType: requestType, email: email, returnOobLink: true };
|
|
1284
|
+
// ActionCodeSettings required for email link sign-in to determine the url where the sign-in will
|
|
1285
|
+
// be completed.
|
|
1286
|
+
if (typeof actionCodeSettings === 'undefined' && requestType === 'EMAIL_SIGNIN') {
|
|
1287
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "`actionCodeSettings` is required when `requestType` === 'EMAIL_SIGNIN'"));
|
|
1288
|
+
}
|
|
1289
|
+
if (typeof actionCodeSettings !== 'undefined' || requestType === 'EMAIL_SIGNIN') {
|
|
1290
|
+
try {
|
|
1291
|
+
var builder = new action_code_settings_builder_1.ActionCodeSettingsBuilder(actionCodeSettings);
|
|
1292
|
+
request = deep_copy_1.deepExtend(request, builder.buildRequest());
|
|
1293
|
+
}
|
|
1294
|
+
catch (e) {
|
|
1295
|
+
return Promise.reject(e);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return this.invokeRequestHandler(this.getAuthUrlBuilder(), FIREBASE_AUTH_GET_OOB_CODE, request)
|
|
1299
|
+
.then(function (response) {
|
|
1300
|
+
// Return the link.
|
|
1301
|
+
return response.oobLink;
|
|
1302
|
+
});
|
|
1303
|
+
};
|
|
1304
|
+
/**
|
|
1305
|
+
* Looks up an OIDC provider configuration by provider ID.
|
|
1306
|
+
*
|
|
1307
|
+
* @param {string} providerId The provider identifier of the configuration to lookup.
|
|
1308
|
+
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the provider configuration information.
|
|
1309
|
+
*/
|
|
1310
|
+
AbstractAuthRequestHandler.prototype.getOAuthIdpConfig = function (providerId) {
|
|
1311
|
+
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
|
1312
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1313
|
+
}
|
|
1314
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_OAUTH_IDP_CONFIG, {}, { providerId: providerId });
|
|
1315
|
+
};
|
|
1316
|
+
/**
|
|
1317
|
+
* Lists the OIDC configurations (single batch only) with a size of maxResults and starting from
|
|
1318
|
+
* the offset as specified by pageToken.
|
|
1319
|
+
*
|
|
1320
|
+
* @param {number=} maxResults The page size, 100 if undefined. This is also the maximum
|
|
1321
|
+
* allowed limit.
|
|
1322
|
+
* @param {string=} pageToken The next page token. If not specified, returns OIDC configurations
|
|
1323
|
+
* without any offset. Configurations are returned in the order they were created from oldest to
|
|
1324
|
+
* newest, relative to the page token offset.
|
|
1325
|
+
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
|
|
1326
|
+
* OIDC configurations and the next page token if available. For the last page, an empty list of provider
|
|
1327
|
+
* configuration and no page token are returned.
|
|
1328
|
+
*/
|
|
1329
|
+
AbstractAuthRequestHandler.prototype.listOAuthIdpConfigs = function (maxResults, pageToken) {
|
|
1330
|
+
if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
|
|
1331
|
+
var request = {
|
|
1332
|
+
pageSize: maxResults,
|
|
1333
|
+
};
|
|
1334
|
+
// Add next page token if provided.
|
|
1335
|
+
if (typeof pageToken !== 'undefined') {
|
|
1336
|
+
request.pageToken = pageToken;
|
|
1337
|
+
}
|
|
1338
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_OAUTH_IDP_CONFIGS, request)
|
|
1339
|
+
.then(function (response) {
|
|
1340
|
+
if (!response.oauthIdpConfigs) {
|
|
1341
|
+
response.oauthIdpConfigs = [];
|
|
1342
|
+
delete response.nextPageToken;
|
|
1343
|
+
}
|
|
1344
|
+
return response;
|
|
1345
|
+
});
|
|
1346
|
+
};
|
|
1347
|
+
/**
|
|
1348
|
+
* Deletes an OIDC configuration identified by a providerId.
|
|
1349
|
+
*
|
|
1350
|
+
* @param {string} providerId The identifier of the OIDC configuration to delete.
|
|
1351
|
+
* @return {Promise<void>} A promise that resolves when the OIDC provider is deleted.
|
|
1352
|
+
*/
|
|
1353
|
+
AbstractAuthRequestHandler.prototype.deleteOAuthIdpConfig = function (providerId) {
|
|
1354
|
+
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
|
1355
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1356
|
+
}
|
|
1357
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_OAUTH_IDP_CONFIG, {}, { providerId: providerId })
|
|
1358
|
+
.then(function () {
|
|
1359
|
+
// Return nothing.
|
|
1360
|
+
});
|
|
1361
|
+
};
|
|
1362
|
+
/**
|
|
1363
|
+
* Creates a new OIDC provider configuration with the properties provided.
|
|
1364
|
+
*
|
|
1365
|
+
* @param {AuthProviderConfig} options The properties to set on the new OIDC provider configuration to be created.
|
|
1366
|
+
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the newly created OIDC
|
|
1367
|
+
* configuration.
|
|
1368
|
+
*/
|
|
1369
|
+
AbstractAuthRequestHandler.prototype.createOAuthIdpConfig = function (options) {
|
|
1370
|
+
// Construct backend request.
|
|
1371
|
+
var request;
|
|
1372
|
+
try {
|
|
1373
|
+
request = auth_config_1.OIDCConfig.buildServerRequest(options) || {};
|
|
1374
|
+
}
|
|
1375
|
+
catch (e) {
|
|
1376
|
+
return Promise.reject(e);
|
|
1377
|
+
}
|
|
1378
|
+
var providerId = options.providerId;
|
|
1379
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_OAUTH_IDP_CONFIG, request, { providerId: providerId })
|
|
1380
|
+
.then(function (response) {
|
|
1381
|
+
if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
|
|
1382
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new OIDC provider configuration');
|
|
1383
|
+
}
|
|
1384
|
+
return response;
|
|
1385
|
+
});
|
|
1386
|
+
};
|
|
1387
|
+
/**
|
|
1388
|
+
* Updates an existing OIDC provider configuration with the properties provided.
|
|
1389
|
+
*
|
|
1390
|
+
* @param {string} providerId The provider identifier of the OIDC configuration to update.
|
|
1391
|
+
* @param {OIDCUpdateAuthProviderRequest} options The properties to update on the existing configuration.
|
|
1392
|
+
* @return {Promise<OIDCConfigServerResponse>} A promise that resolves with the modified provider
|
|
1393
|
+
* configuration.
|
|
1394
|
+
*/
|
|
1395
|
+
AbstractAuthRequestHandler.prototype.updateOAuthIdpConfig = function (providerId, options) {
|
|
1396
|
+
if (!auth_config_1.OIDCConfig.isProviderId(providerId)) {
|
|
1397
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1398
|
+
}
|
|
1399
|
+
// Construct backend request.
|
|
1400
|
+
var request;
|
|
1401
|
+
try {
|
|
1402
|
+
request = auth_config_1.OIDCConfig.buildServerRequest(options, true) || {};
|
|
1403
|
+
}
|
|
1404
|
+
catch (e) {
|
|
1405
|
+
return Promise.reject(e);
|
|
1406
|
+
}
|
|
1407
|
+
var updateMask = utils.generateUpdateMask(request);
|
|
1408
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_OAUTH_IDP_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
|
|
1409
|
+
.then(function (response) {
|
|
1410
|
+
if (!auth_config_1.OIDCConfig.getProviderIdFromResourceName(response.name)) {
|
|
1411
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update OIDC provider configuration');
|
|
1412
|
+
}
|
|
1413
|
+
return response;
|
|
1414
|
+
});
|
|
1415
|
+
};
|
|
1416
|
+
/**
|
|
1417
|
+
* Looks up an SAML provider configuration by provider ID.
|
|
1418
|
+
*
|
|
1419
|
+
* @param {string} providerId The provider identifier of the configuration to lookup.
|
|
1420
|
+
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the provider configuration information.
|
|
1421
|
+
*/
|
|
1422
|
+
AbstractAuthRequestHandler.prototype.getInboundSamlConfig = function (providerId) {
|
|
1423
|
+
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
|
1424
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1425
|
+
}
|
|
1426
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), GET_INBOUND_SAML_CONFIG, {}, { providerId: providerId });
|
|
1427
|
+
};
|
|
1428
|
+
/**
|
|
1429
|
+
* Lists the SAML configurations (single batch only) with a size of maxResults and starting from
|
|
1430
|
+
* the offset as specified by pageToken.
|
|
1431
|
+
*
|
|
1432
|
+
* @param {number=} maxResults The page size, 100 if undefined. This is also the maximum
|
|
1433
|
+
* allowed limit.
|
|
1434
|
+
* @param {string=} pageToken The next page token. If not specified, returns SAML configurations starting
|
|
1435
|
+
* without any offset. Configurations are returned in the order they were created from oldest to
|
|
1436
|
+
* newest, relative to the page token offset.
|
|
1437
|
+
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
|
|
1438
|
+
* SAML configurations and the next page token if available. For the last page, an empty list of provider
|
|
1439
|
+
* configuration and no page token are returned.
|
|
1440
|
+
*/
|
|
1441
|
+
AbstractAuthRequestHandler.prototype.listInboundSamlConfigs = function (maxResults, pageToken) {
|
|
1442
|
+
if (maxResults === void 0) { maxResults = MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE; }
|
|
1443
|
+
var request = {
|
|
1444
|
+
pageSize: maxResults,
|
|
1445
|
+
};
|
|
1446
|
+
// Add next page token if provided.
|
|
1447
|
+
if (typeof pageToken !== 'undefined') {
|
|
1448
|
+
request.pageToken = pageToken;
|
|
1449
|
+
}
|
|
1450
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), LIST_INBOUND_SAML_CONFIGS, request)
|
|
1451
|
+
.then(function (response) {
|
|
1452
|
+
if (!response.inboundSamlConfigs) {
|
|
1453
|
+
response.inboundSamlConfigs = [];
|
|
1454
|
+
delete response.nextPageToken;
|
|
1455
|
+
}
|
|
1456
|
+
return response;
|
|
1457
|
+
});
|
|
1458
|
+
};
|
|
1459
|
+
/**
|
|
1460
|
+
* Deletes a SAML configuration identified by a providerId.
|
|
1461
|
+
*
|
|
1462
|
+
* @param {string} providerId The identifier of the SAML configuration to delete.
|
|
1463
|
+
* @return {Promise<void>} A promise that resolves when the SAML provider is deleted.
|
|
1464
|
+
*/
|
|
1465
|
+
AbstractAuthRequestHandler.prototype.deleteInboundSamlConfig = function (providerId) {
|
|
1466
|
+
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
|
1467
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1468
|
+
}
|
|
1469
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), DELETE_INBOUND_SAML_CONFIG, {}, { providerId: providerId })
|
|
1470
|
+
.then(function () {
|
|
1471
|
+
// Return nothing.
|
|
1472
|
+
});
|
|
1473
|
+
};
|
|
1474
|
+
/**
|
|
1475
|
+
* Creates a new SAML provider configuration with the properties provided.
|
|
1476
|
+
*
|
|
1477
|
+
* @param {AuthProviderConfig} options The properties to set on the new SAML provider configuration to be created.
|
|
1478
|
+
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the newly created SAML
|
|
1479
|
+
* configuration.
|
|
1480
|
+
*/
|
|
1481
|
+
AbstractAuthRequestHandler.prototype.createInboundSamlConfig = function (options) {
|
|
1482
|
+
// Construct backend request.
|
|
1483
|
+
var request;
|
|
1484
|
+
try {
|
|
1485
|
+
request = auth_config_1.SAMLConfig.buildServerRequest(options) || {};
|
|
1486
|
+
}
|
|
1487
|
+
catch (e) {
|
|
1488
|
+
return Promise.reject(e);
|
|
1489
|
+
}
|
|
1490
|
+
var providerId = options.providerId;
|
|
1491
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), CREATE_INBOUND_SAML_CONFIG, request, { providerId: providerId })
|
|
1492
|
+
.then(function (response) {
|
|
1493
|
+
if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
|
|
1494
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new SAML provider configuration');
|
|
1495
|
+
}
|
|
1496
|
+
return response;
|
|
1497
|
+
});
|
|
1498
|
+
};
|
|
1499
|
+
/**
|
|
1500
|
+
* Updates an existing SAML provider configuration with the properties provided.
|
|
1501
|
+
*
|
|
1502
|
+
* @param {string} providerId The provider identifier of the SAML configuration to update.
|
|
1503
|
+
* @param {SAMLUpdateAuthProviderRequest} options The properties to update on the existing configuration.
|
|
1504
|
+
* @return {Promise<SAMLConfigServerResponse>} A promise that resolves with the modified provider
|
|
1505
|
+
* configuration.
|
|
1506
|
+
*/
|
|
1507
|
+
AbstractAuthRequestHandler.prototype.updateInboundSamlConfig = function (providerId, options) {
|
|
1508
|
+
if (!auth_config_1.SAMLConfig.isProviderId(providerId)) {
|
|
1509
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
|
|
1510
|
+
}
|
|
1511
|
+
// Construct backend request.
|
|
1512
|
+
var request;
|
|
1513
|
+
try {
|
|
1514
|
+
request = auth_config_1.SAMLConfig.buildServerRequest(options, true) || {};
|
|
1515
|
+
}
|
|
1516
|
+
catch (e) {
|
|
1517
|
+
return Promise.reject(e);
|
|
1518
|
+
}
|
|
1519
|
+
var updateMask = utils.generateUpdateMask(request);
|
|
1520
|
+
return this.invokeRequestHandler(this.getProjectConfigUrlBuilder(), UPDATE_INBOUND_SAML_CONFIG, request, { providerId: providerId, updateMask: updateMask.join(',') })
|
|
1521
|
+
.then(function (response) {
|
|
1522
|
+
if (!auth_config_1.SAMLConfig.getProviderIdFromResourceName(response.name)) {
|
|
1523
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update SAML provider configuration');
|
|
1524
|
+
}
|
|
1525
|
+
return response;
|
|
1526
|
+
});
|
|
1527
|
+
};
|
|
1528
|
+
/**
|
|
1529
|
+
* Invokes the request handler based on the API settings object passed.
|
|
1530
|
+
*
|
|
1531
|
+
* @param {AuthResourceUrlBuilder} urlBuilder The URL builder for Auth endpoints.
|
|
1532
|
+
* @param {ApiSettings} apiSettings The API endpoint settings to apply to request and response.
|
|
1533
|
+
* @param {object} requestData The request data.
|
|
1534
|
+
* @param {object=} additionalResourceParams Additional resource related params if needed.
|
|
1535
|
+
* @return {Promise<object>} A promise that resolves with the response.
|
|
1536
|
+
*/
|
|
1537
|
+
AbstractAuthRequestHandler.prototype.invokeRequestHandler = function (urlBuilder, apiSettings, requestData, additionalResourceParams) {
|
|
1538
|
+
var _this = this;
|
|
1539
|
+
return urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams)
|
|
1540
|
+
.then(function (url) {
|
|
1541
|
+
// Validate request.
|
|
1542
|
+
var requestValidator = apiSettings.getRequestValidator();
|
|
1543
|
+
requestValidator(requestData);
|
|
1544
|
+
// Process request.
|
|
1545
|
+
var req = {
|
|
1546
|
+
method: apiSettings.getHttpMethod(),
|
|
1547
|
+
url: url,
|
|
1548
|
+
headers: FIREBASE_AUTH_HEADER,
|
|
1549
|
+
data: requestData,
|
|
1550
|
+
timeout: FIREBASE_AUTH_TIMEOUT,
|
|
1551
|
+
};
|
|
1552
|
+
return _this.httpClient.send(req);
|
|
1553
|
+
})
|
|
1554
|
+
.then(function (response) {
|
|
1555
|
+
// Validate response.
|
|
1556
|
+
var responseValidator = apiSettings.getResponseValidator();
|
|
1557
|
+
responseValidator(response.data);
|
|
1558
|
+
// Return entire response.
|
|
1559
|
+
return response.data;
|
|
1560
|
+
})
|
|
1561
|
+
.catch(function (err) {
|
|
1562
|
+
if (err instanceof api_request_1.HttpError) {
|
|
1563
|
+
var error = err.response.data;
|
|
1564
|
+
var errorCode = AbstractAuthRequestHandler.getErrorCode(error);
|
|
1565
|
+
if (!errorCode) {
|
|
1566
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Error returned from server: ' + error + '. Additionally, an ' +
|
|
1567
|
+
'internal error occurred while attempting to extract the ' +
|
|
1568
|
+
'errorcode from the error.');
|
|
1569
|
+
}
|
|
1570
|
+
throw error_1.FirebaseAuthError.fromServerError(errorCode, /* message */ undefined, error);
|
|
1571
|
+
}
|
|
1572
|
+
throw err;
|
|
1573
|
+
});
|
|
1574
|
+
};
|
|
1575
|
+
/**
|
|
1576
|
+
* @return {AuthResourceUrlBuilder} The current Auth user management resource URL builder.
|
|
1577
|
+
*/
|
|
1578
|
+
AbstractAuthRequestHandler.prototype.getAuthUrlBuilder = function () {
|
|
1579
|
+
if (!this.authUrlBuilder) {
|
|
1580
|
+
this.authUrlBuilder = this.newAuthUrlBuilder();
|
|
1581
|
+
}
|
|
1582
|
+
return this.authUrlBuilder;
|
|
1583
|
+
};
|
|
1584
|
+
/**
|
|
1585
|
+
* @return {AuthResourceUrlBuilder} The current project config resource URL builder.
|
|
1586
|
+
*/
|
|
1587
|
+
AbstractAuthRequestHandler.prototype.getProjectConfigUrlBuilder = function () {
|
|
1588
|
+
if (!this.projectConfigUrlBuilder) {
|
|
1589
|
+
this.projectConfigUrlBuilder = this.newProjectConfigUrlBuilder();
|
|
1590
|
+
}
|
|
1591
|
+
return this.projectConfigUrlBuilder;
|
|
1592
|
+
};
|
|
1593
|
+
return AbstractAuthRequestHandler;
|
|
1594
|
+
}());
|
|
1595
|
+
exports.AbstractAuthRequestHandler = AbstractAuthRequestHandler;
|
|
1596
|
+
/** Instantiates the getTenant endpoint settings. */
|
|
1597
|
+
var GET_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'GET')
|
|
1598
|
+
// Set response validator.
|
|
1599
|
+
.setResponseValidator(function (response) {
|
|
1600
|
+
// Response should always contain at least the tenant name.
|
|
1601
|
+
if (!validator.isNonEmptyString(response.name)) {
|
|
1602
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to get tenant');
|
|
1603
|
+
}
|
|
1604
|
+
});
|
|
1605
|
+
/** Instantiates the deleteTenant endpoint settings. */
|
|
1606
|
+
var DELETE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}', 'DELETE');
|
|
1607
|
+
/** Instantiates the updateTenant endpoint settings. */
|
|
1608
|
+
var UPDATE_TENANT = new api_request_1.ApiSettings('/tenants/{tenantId}?updateMask={updateMask}', 'PATCH')
|
|
1609
|
+
// Set response validator.
|
|
1610
|
+
.setResponseValidator(function (response) {
|
|
1611
|
+
// Response should always contain at least the tenant name.
|
|
1612
|
+
if (!validator.isNonEmptyString(response.name) ||
|
|
1613
|
+
!tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
|
|
1614
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to update tenant');
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
/** Instantiates the listTenants endpoint settings. */
|
|
1618
|
+
var LIST_TENANTS = new api_request_1.ApiSettings('/tenants', 'GET')
|
|
1619
|
+
// Set request validator.
|
|
1620
|
+
.setRequestValidator(function (request) {
|
|
1621
|
+
// Validate next page token.
|
|
1622
|
+
if (typeof request.pageToken !== 'undefined' &&
|
|
1623
|
+
!validator.isNonEmptyString(request.pageToken)) {
|
|
1624
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
|
|
1625
|
+
}
|
|
1626
|
+
// Validate max results.
|
|
1627
|
+
if (!validator.isNumber(request.pageSize) ||
|
|
1628
|
+
request.pageSize <= 0 ||
|
|
1629
|
+
request.pageSize > MAX_LIST_TENANT_PAGE_SIZE) {
|
|
1630
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive non-zero number that does not exceed ' +
|
|
1631
|
+
("the allowed " + MAX_LIST_TENANT_PAGE_SIZE + "."));
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
/** Instantiates the createTenant endpoint settings. */
|
|
1635
|
+
var CREATE_TENANT = new api_request_1.ApiSettings('/tenants', 'POST')
|
|
1636
|
+
// Set response validator.
|
|
1637
|
+
.setResponseValidator(function (response) {
|
|
1638
|
+
// Response should always contain at least the tenant name.
|
|
1639
|
+
if (!validator.isNonEmptyString(response.name) ||
|
|
1640
|
+
!tenant_1.Tenant.getTenantIdFromResourceName(response.name)) {
|
|
1641
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new tenant');
|
|
1642
|
+
}
|
|
1643
|
+
});
|
|
1644
|
+
/**
|
|
1645
|
+
* Utility for sending requests to Auth server that are Auth instance related. This includes user and
|
|
1646
|
+
* tenant management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
|
|
1647
|
+
* additional tenant management related APIs.
|
|
1648
|
+
*/
|
|
1649
|
+
var AuthRequestHandler = /** @class */ (function (_super) {
|
|
1650
|
+
__extends(AuthRequestHandler, _super);
|
|
1651
|
+
/**
|
|
1652
|
+
* The FirebaseAuthRequestHandler constructor used to initialize an instance using a FirebaseApp.
|
|
1653
|
+
*
|
|
1654
|
+
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
|
1655
|
+
* @constructor.
|
|
1656
|
+
*/
|
|
1657
|
+
function AuthRequestHandler(app) {
|
|
1658
|
+
var _this = _super.call(this, app) || this;
|
|
1659
|
+
_this.tenantMgmtResourceBuilder = new AuthResourceUrlBuilder(app, 'v2');
|
|
1660
|
+
return _this;
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* @return {AuthResourceUrlBuilder} A new Auth user management resource URL builder instance.
|
|
1664
|
+
*/
|
|
1665
|
+
AuthRequestHandler.prototype.newAuthUrlBuilder = function () {
|
|
1666
|
+
return new AuthResourceUrlBuilder(this.app, 'v1');
|
|
1667
|
+
};
|
|
1668
|
+
/**
|
|
1669
|
+
* @return {AuthResourceUrlBuilder} A new project config resource URL builder instance.
|
|
1670
|
+
*/
|
|
1671
|
+
AuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
|
|
1672
|
+
return new AuthResourceUrlBuilder(this.app, 'v2');
|
|
1673
|
+
};
|
|
1674
|
+
/**
|
|
1675
|
+
* Looks up a tenant by tenant ID.
|
|
1676
|
+
*
|
|
1677
|
+
* @param {string} tenantId The tenant identifier of the tenant to lookup.
|
|
1678
|
+
* @return {Promise<TenantServerResponse>} A promise that resolves with the tenant information.
|
|
1679
|
+
*/
|
|
1680
|
+
AuthRequestHandler.prototype.getTenant = function (tenantId) {
|
|
1681
|
+
if (!validator.isNonEmptyString(tenantId)) {
|
|
1682
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
|
1683
|
+
}
|
|
1684
|
+
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, GET_TENANT, {}, { tenantId: tenantId })
|
|
1685
|
+
.then(function (response) {
|
|
1686
|
+
return response;
|
|
1687
|
+
});
|
|
1688
|
+
};
|
|
1689
|
+
/**
|
|
1690
|
+
* Exports the tenants (single batch only) with a size of maxResults and starting from
|
|
1691
|
+
* the offset as specified by pageToken.
|
|
1692
|
+
*
|
|
1693
|
+
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
|
|
1694
|
+
* allowed limit.
|
|
1695
|
+
* @param {string=} pageToken The next page token. If not specified, returns tenants starting
|
|
1696
|
+
* without any offset. Tenants are returned in the order they were created from oldest to
|
|
1697
|
+
* newest, relative to the page token offset.
|
|
1698
|
+
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
|
|
1699
|
+
* tenants and the next page token if available. For the last page, an empty list of tenants
|
|
1700
|
+
* and no page token are returned.
|
|
1701
|
+
*/
|
|
1702
|
+
AuthRequestHandler.prototype.listTenants = function (maxResults, pageToken) {
|
|
1703
|
+
if (maxResults === void 0) { maxResults = MAX_LIST_TENANT_PAGE_SIZE; }
|
|
1704
|
+
var request = {
|
|
1705
|
+
pageSize: maxResults,
|
|
1706
|
+
pageToken: pageToken,
|
|
1707
|
+
};
|
|
1708
|
+
// Remove next page token if not provided.
|
|
1709
|
+
if (typeof request.pageToken === 'undefined') {
|
|
1710
|
+
delete request.pageToken;
|
|
1711
|
+
}
|
|
1712
|
+
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, LIST_TENANTS, request)
|
|
1713
|
+
.then(function (response) {
|
|
1714
|
+
if (!response.tenants) {
|
|
1715
|
+
response.tenants = [];
|
|
1716
|
+
delete response.nextPageToken;
|
|
1717
|
+
}
|
|
1718
|
+
return response;
|
|
1719
|
+
});
|
|
1720
|
+
};
|
|
1721
|
+
/**
|
|
1722
|
+
* Deletes a tenant identified by a tenantId.
|
|
1723
|
+
*
|
|
1724
|
+
* @param {string} tenantId The identifier of the tenant to delete.
|
|
1725
|
+
* @return {Promise<void>} A promise that resolves when the tenant is deleted.
|
|
1726
|
+
*/
|
|
1727
|
+
AuthRequestHandler.prototype.deleteTenant = function (tenantId) {
|
|
1728
|
+
if (!validator.isNonEmptyString(tenantId)) {
|
|
1729
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
|
1730
|
+
}
|
|
1731
|
+
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, DELETE_TENANT, {}, { tenantId: tenantId })
|
|
1732
|
+
.then(function () {
|
|
1733
|
+
// Return nothing.
|
|
1734
|
+
});
|
|
1735
|
+
};
|
|
1736
|
+
/**
|
|
1737
|
+
* Creates a new tenant with the properties provided.
|
|
1738
|
+
*
|
|
1739
|
+
* @param {TenantOptions} tenantOptions The properties to set on the new tenant to be created.
|
|
1740
|
+
* @return {Promise<TenantServerResponse>} A promise that resolves with the newly created tenant object.
|
|
1741
|
+
*/
|
|
1742
|
+
AuthRequestHandler.prototype.createTenant = function (tenantOptions) {
|
|
1743
|
+
try {
|
|
1744
|
+
// Construct backend request.
|
|
1745
|
+
var request = tenant_1.Tenant.buildServerRequest(tenantOptions, true);
|
|
1746
|
+
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, CREATE_TENANT, request)
|
|
1747
|
+
.then(function (response) {
|
|
1748
|
+
return response;
|
|
1749
|
+
});
|
|
1750
|
+
}
|
|
1751
|
+
catch (e) {
|
|
1752
|
+
return Promise.reject(e);
|
|
1753
|
+
}
|
|
1754
|
+
};
|
|
1755
|
+
/**
|
|
1756
|
+
* Updates an existing tenant with the properties provided.
|
|
1757
|
+
*
|
|
1758
|
+
* @param {string} tenantId The tenant identifier of the tenant to update.
|
|
1759
|
+
* @param {TenantOptions} tenantOptions The properties to update on the existing tenant.
|
|
1760
|
+
* @return {Promise<TenantServerResponse>} A promise that resolves with the modified tenant object.
|
|
1761
|
+
*/
|
|
1762
|
+
AuthRequestHandler.prototype.updateTenant = function (tenantId, tenantOptions) {
|
|
1763
|
+
if (!validator.isNonEmptyString(tenantId)) {
|
|
1764
|
+
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID));
|
|
1765
|
+
}
|
|
1766
|
+
try {
|
|
1767
|
+
// Construct backend request.
|
|
1768
|
+
var request = tenant_1.Tenant.buildServerRequest(tenantOptions, false);
|
|
1769
|
+
// Do not traverse deep into testPhoneNumbers. The entire content should be replaced
|
|
1770
|
+
// and not just specific phone numbers.
|
|
1771
|
+
var updateMask = utils.generateUpdateMask(request, ['testPhoneNumbers']);
|
|
1772
|
+
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, UPDATE_TENANT, request, { tenantId: tenantId, updateMask: updateMask.join(',') })
|
|
1773
|
+
.then(function (response) {
|
|
1774
|
+
return response;
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1777
|
+
catch (e) {
|
|
1778
|
+
return Promise.reject(e);
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
return AuthRequestHandler;
|
|
1782
|
+
}(AbstractAuthRequestHandler));
|
|
1783
|
+
exports.AuthRequestHandler = AuthRequestHandler;
|
|
1784
|
+
/**
|
|
1785
|
+
* Utility for sending requests to Auth server that are tenant Auth instance related. This includes user
|
|
1786
|
+
* management related APIs for specified tenants.
|
|
1787
|
+
* This extends the BaseFirebaseAuthRequestHandler class.
|
|
1788
|
+
*/
|
|
1789
|
+
var TenantAwareAuthRequestHandler = /** @class */ (function (_super) {
|
|
1790
|
+
__extends(TenantAwareAuthRequestHandler, _super);
|
|
1791
|
+
/**
|
|
1792
|
+
* The FirebaseTenantRequestHandler constructor used to initialize an instance using a
|
|
1793
|
+
* FirebaseApp and a tenant ID.
|
|
1794
|
+
*
|
|
1795
|
+
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
|
|
1796
|
+
* @param {string} tenantId The request handler's tenant ID.
|
|
1797
|
+
* @constructor
|
|
1798
|
+
*/
|
|
1799
|
+
function TenantAwareAuthRequestHandler(app, tenantId) {
|
|
1800
|
+
var _this = _super.call(this, app) || this;
|
|
1801
|
+
_this.tenantId = tenantId;
|
|
1802
|
+
return _this;
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* @return {AuthResourceUrlBuilder} A new Auth user management resource URL builder instance.
|
|
1806
|
+
*/
|
|
1807
|
+
TenantAwareAuthRequestHandler.prototype.newAuthUrlBuilder = function () {
|
|
1808
|
+
return new TenantAwareAuthResourceUrlBuilder(this.app, 'v1', this.tenantId);
|
|
1809
|
+
};
|
|
1810
|
+
/**
|
|
1811
|
+
* @return {AuthResourceUrlBuilder} A new project config resource URL builder instance.
|
|
1812
|
+
*/
|
|
1813
|
+
TenantAwareAuthRequestHandler.prototype.newProjectConfigUrlBuilder = function () {
|
|
1814
|
+
return new TenantAwareAuthResourceUrlBuilder(this.app, 'v2', this.tenantId);
|
|
1815
|
+
};
|
|
1816
|
+
/**
|
|
1817
|
+
* Imports the list of users provided to Firebase Auth. This is useful when
|
|
1818
|
+
* migrating from an external authentication system without having to use the Firebase CLI SDK.
|
|
1819
|
+
* At most, 1000 users are allowed to be imported one at a time.
|
|
1820
|
+
* When importing a list of password users, UserImportOptions are required to be specified.
|
|
1821
|
+
*
|
|
1822
|
+
* Overrides the superclass methods by adding an additional check to match tenant IDs of
|
|
1823
|
+
* imported user records if present.
|
|
1824
|
+
*
|
|
1825
|
+
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
|
|
1826
|
+
* @param {UserImportOptions=} options The user import options, required when the users provided
|
|
1827
|
+
* include password credentials.
|
|
1828
|
+
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
|
|
1829
|
+
* with the result of the import. This includes the number of successful imports, the number
|
|
1830
|
+
* of failed uploads and their corresponding errors.
|
|
1831
|
+
*/
|
|
1832
|
+
TenantAwareAuthRequestHandler.prototype.uploadAccount = function (users, options) {
|
|
1833
|
+
var _this = this;
|
|
1834
|
+
// Add additional check to match tenant ID of imported user records.
|
|
1835
|
+
users.forEach(function (user, index) {
|
|
1836
|
+
if (validator.isNonEmptyString(user.tenantId) &&
|
|
1837
|
+
user.tenantId !== _this.tenantId) {
|
|
1838
|
+
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISMATCHING_TENANT_ID, "UserRecord of index \"" + index + "\" has mismatching tenant ID \"" + user.tenantId + "\"");
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
return _super.prototype.uploadAccount.call(this, users, options);
|
|
1842
|
+
};
|
|
1843
|
+
return TenantAwareAuthRequestHandler;
|
|
1844
|
+
}(AbstractAuthRequestHandler));
|
|
1845
|
+
exports.TenantAwareAuthRequestHandler = TenantAwareAuthRequestHandler;
|
|
1846
|
+
function emulatorHost() {
|
|
1847
|
+
return process.env.FIREBASE_AUTH_EMULATOR_HOST;
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* When true the SDK should communicate with the Auth Emulator for all API
|
|
1851
|
+
* calls and also produce unsigned tokens.
|
|
1852
|
+
*/
|
|
1853
|
+
function useEmulator() {
|
|
1854
|
+
return !!emulatorHost();
|
|
1855
|
+
}
|
|
1856
|
+
exports.useEmulator = useEmulator;
|