firebase-admin 9.3.0 → 9.5.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.
Files changed (82) hide show
  1. package/lib/auth/action-code-settings-builder.js +1 -1
  2. package/lib/auth/auth-api-request.js +98 -25
  3. package/lib/auth/auth-config.js +15 -15
  4. package/lib/auth/auth.js +82 -61
  5. package/lib/auth/identifier.js +3 -2
  6. package/lib/auth/index.d.ts +1868 -0
  7. package/lib/{credential/credential-interfaces.js → auth/index.js} +1 -1
  8. package/lib/auth/tenant-manager.js +1 -1
  9. package/lib/auth/tenant.js +7 -1
  10. package/lib/auth/token-generator.js +6 -4
  11. package/lib/auth/token-verifier.js +32 -36
  12. package/lib/auth/user-import-builder.js +18 -15
  13. package/lib/auth/user-record.js +4 -4
  14. package/lib/credential/credential-internal.js +1 -2
  15. package/lib/credential/credential.js +8 -122
  16. package/lib/credential/index.d.ts +169 -0
  17. package/lib/credential/index.js +5 -17
  18. package/lib/database/database-internal.js +19 -26
  19. package/lib/database/index.d.ts +89 -0
  20. package/lib/database/index.js +12 -28
  21. package/lib/default-namespace.js +2 -1
  22. package/lib/firebase-app.js +26 -48
  23. package/lib/firebase-namespace-api.d.ts +238 -0
  24. package/lib/{firebase-service.js → firebase-namespace-api.js} +2 -2
  25. package/lib/{database/database.js → firebase-namespace.d.ts} +14 -7
  26. package/lib/firebase-namespace.js +22 -92
  27. package/lib/firestore/firestore-internal.js +2 -19
  28. package/lib/firestore/index.d.ts +50 -0
  29. package/lib/firestore/index.js +28 -43
  30. package/lib/index.d.ts +3 -932
  31. package/lib/index.js +2 -1
  32. package/lib/instance-id/index.d.ts +81 -0
  33. package/lib/instance-id/index.js +1 -10
  34. package/lib/instance-id/instance-id-request-internal.js +2 -1
  35. package/lib/instance-id/instance-id.js +1 -19
  36. package/lib/machine-learning/index.d.ts +249 -0
  37. package/lib/{messaging/messaging-types.js → machine-learning/index.js} +2 -2
  38. package/lib/machine-learning/machine-learning-api-client.js +1 -1
  39. package/lib/machine-learning/machine-learning-utils.js +1 -1
  40. package/lib/machine-learning/machine-learning.js +3 -22
  41. package/lib/messaging/batch-request-internal.js +1 -1
  42. package/lib/messaging/index.d.ts +1174 -0
  43. package/lib/messaging/index.js +1 -24
  44. package/lib/messaging/messaging-api-request-internal.js +2 -1
  45. package/lib/messaging/messaging-errors-internal.js +1 -1
  46. package/lib/messaging/messaging-internal.js +1 -1
  47. package/lib/messaging/messaging.js +21 -25
  48. package/lib/project-management/android-app.js +7 -6
  49. package/lib/project-management/index.d.ts +363 -0
  50. package/lib/project-management/index.js +23 -25
  51. package/lib/project-management/ios-app.js +5 -4
  52. package/lib/project-management/project-management-api-request-internal.js +5 -5
  53. package/lib/project-management/project-management.js +9 -26
  54. package/lib/remote-config/index.d.ts +359 -0
  55. package/lib/remote-config/index.js +1 -26
  56. package/lib/remote-config/remote-config-api-client-internal.js +3 -3
  57. package/lib/remote-config/remote-config.js +15 -32
  58. package/lib/security-rules/index.d.ts +216 -0
  59. package/lib/security-rules/index.js +1 -24
  60. package/lib/security-rules/security-rules-api-client-internal.js +1 -1
  61. package/lib/security-rules/security-rules-internal.js +1 -1
  62. package/lib/security-rules/security-rules.js +6 -15
  63. package/lib/storage/index.d.ts +60 -0
  64. package/lib/storage/index.js +1 -10
  65. package/lib/storage/storage.js +2 -19
  66. package/lib/utils/api-request.js +10 -3
  67. package/lib/utils/deep-copy.js +2 -1
  68. package/lib/utils/error.js +2 -1
  69. package/lib/utils/index.js +6 -5
  70. package/lib/utils/validator.js +2 -1
  71. package/package.json +15 -12
  72. package/lib/auth.d.ts +0 -2016
  73. package/lib/credential.d.ts +0 -150
  74. package/lib/database.d.ts +0 -1663
  75. package/lib/instance-id.d.ts +0 -37
  76. package/lib/messaging.d.ts +0 -1341
  77. package/lib/project-management/app-metadata.js +0 -37
  78. package/lib/project-management.d.ts +0 -361
  79. package/lib/remote-config/remote-config-api-client.js +0 -36
  80. package/lib/remote-config.d.ts +0 -350
  81. package/lib/security-rules.d.ts +0 -192
  82. package/lib/storage.d.ts +0 -40
@@ -1,4 +1,4 @@
1
- /*! firebase-admin v9.3.0 */
1
+ /*! firebase-admin v9.5.0 */
2
2
  "use strict";
3
3
  /*!
4
4
  * Copyright 2018 Google Inc.
@@ -1,6 +1,7 @@
1
- /*! firebase-admin v9.3.0 */
1
+ /*! firebase-admin v9.5.0 */
2
2
  "use strict";
3
3
  /*!
4
+ * @license
4
5
  * Copyright 2017 Google Inc.
5
6
  *
6
7
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,7 +30,7 @@ var __extends = (this && this.__extends) || (function () {
29
30
  };
30
31
  })();
31
32
  Object.defineProperty(exports, "__esModule", { value: true });
32
- 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;
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;
33
34
  var validator = require("../utils/validator");
34
35
  var deep_copy_1 = require("../utils/deep-copy");
35
36
  var identifier_1 = require("./identifier");
@@ -103,10 +104,9 @@ var AuthResourceUrlBuilder = /** @class */ (function () {
103
104
  if (version === void 0) { version = 'v1'; }
104
105
  this.app = app;
105
106
  this.version = version;
106
- var emulatorHost = process.env.FIREBASE_AUTH_EMULATOR_HOST;
107
- if (emulatorHost) {
107
+ if (useEmulator()) {
108
108
  this.urlFormat = utils.formatString(FIREBASE_AUTH_EMULATOR_BASE_URL_FORMAT, {
109
- host: emulatorHost
109
+ host: emulatorHost()
110
110
  });
111
111
  }
112
112
  else {
@@ -169,10 +169,9 @@ var TenantAwareAuthResourceUrlBuilder = /** @class */ (function (_super) {
169
169
  _this.app = app;
170
170
  _this.version = version;
171
171
  _this.tenantId = tenantId;
172
- var emulatorHost = process.env.FIREBASE_AUTH_EMULATOR_HOST;
173
- if (emulatorHost) {
172
+ if (useEmulator()) {
174
173
  _this.urlFormat = utils.formatString(FIREBASE_AUTH_EMULATOR_TENANT_URL_FORMAT, {
175
- host: emulatorHost
174
+ host: emulatorHost()
176
175
  });
177
176
  }
178
177
  else {
@@ -197,6 +196,23 @@ var TenantAwareAuthResourceUrlBuilder = /** @class */ (function (_super) {
197
196
  };
198
197
  return TenantAwareAuthResourceUrlBuilder;
199
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));
200
216
  /**
201
217
  * Validates an AuthFactorInfo object. All unsupported parameters
202
218
  * are removed from the original request. If an invalid field is passed
@@ -223,7 +239,7 @@ function validateAuthFactorInfo(request, writeOperationType) {
223
239
  var uidRequired = writeOperationType !== WriteOperationType.Create;
224
240
  if ((typeof request.mfaEnrollmentId !== 'undefined' || uidRequired) &&
225
241
  !validator.isNonEmptyString(request.mfaEnrollmentId)) {
226
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, "The second factor \"uid\" must be a valid non-empty string.");
242
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, 'The second factor "uid" must be a valid non-empty string.');
227
243
  }
228
244
  if (typeof request.displayName !== 'undefined' &&
229
245
  !validator.isString(request.displayName)) {
@@ -233,20 +249,20 @@ function validateAuthFactorInfo(request, writeOperationType) {
233
249
  if (typeof request.enrolledAt !== 'undefined' &&
234
250
  !validator.isISODateString(request.enrolledAt)) {
235
251
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLMENT_TIME, "The second factor \"enrollmentTime\" for \"" + authFactorInfoIdentifier + "\" must be a valid " +
236
- "UTC date string.");
252
+ 'UTC date string.');
237
253
  }
238
254
  // Validate required fields depending on second factor type.
239
255
  if (typeof request.phoneInfo !== 'undefined') {
240
256
  // phoneNumber should be a string and a valid phone number.
241
257
  if (!validator.isPhoneNumber(request.phoneInfo)) {
242
258
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER, "The second factor \"phoneNumber\" for \"" + authFactorInfoIdentifier + "\" must be a non-empty " +
243
- "E.164 standard compliant identifier string.");
259
+ 'E.164 standard compliant identifier string.');
244
260
  }
245
261
  }
246
262
  else {
247
263
  // Invalid second factor. For example, a phone second factor may have been provided without
248
264
  // a phone number. A TOTP based second factor may require a secret key, etc.
249
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLED_FACTORS, "MFAInfo object provided is invalid.");
265
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLED_FACTORS, 'MFAInfo object provided is invalid.');
250
266
  }
251
267
  }
252
268
  /**
@@ -321,6 +337,8 @@ function validateCreateEditRequest(request, writeOperationType) {
321
337
  phoneNumber: true,
322
338
  customAttributes: true,
323
339
  validSince: true,
340
+ // Pass linkProviderUserInfo only for updates (i.e. not for uploads.)
341
+ linkProviderUserInfo: !uploadAccountRequest,
324
342
  // Pass tenantId only for uploadAccount requests.
325
343
  tenantId: uploadAccountRequest,
326
344
  passwordHash: uploadAccountRequest,
@@ -465,6 +483,10 @@ function validateCreateEditRequest(request, writeOperationType) {
465
483
  validateProviderUserInfo(providerUserInfoEntry);
466
484
  });
467
485
  }
486
+ // linkProviderUserInfo must be a (single) UserProvider value.
487
+ if (typeof request.linkProviderUserInfo !== 'undefined') {
488
+ validateProviderUserInfo(request.linkProviderUserInfo);
489
+ }
468
490
  // mfaInfo is used for importUsers.
469
491
  // mfa.enrollments is used for setAccountInfo.
470
492
  // enrollments has to be an array of valid AuthFactorInfo requests.
@@ -521,7 +543,7 @@ exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = new api_request_1.ApiSettings('/account
521
543
  if (!validator.isNumber(request.maxResults) ||
522
544
  request.maxResults <= 0 ||
523
545
  request.maxResults > MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE) {
524
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive integer that does not exceed " +
546
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
525
547
  (MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE + "."));
526
548
  }
527
549
  });
@@ -535,7 +557,7 @@ exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = new api_request_1.ApiSettings('/account
535
557
  })
536
558
  // Set response validator.
537
559
  .setResponseValidator(function (response) {
538
- if (!response.users) {
560
+ if (!response.users || !response.users.length) {
539
561
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
540
562
  }
541
563
  });
@@ -609,11 +631,11 @@ exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = new api_request_1.ApiSettings('/account
609
631
  .setRequestValidator(function (request) {
610
632
  // signupNewUser does not support customAttributes.
611
633
  if (typeof request.customAttributes !== 'undefined') {
612
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"customAttributes\" cannot be set when creating a new user.");
634
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"customAttributes" cannot be set when creating a new user.');
613
635
  }
614
636
  // signupNewUser does not support validSince.
615
637
  if (typeof request.validSince !== 'undefined') {
616
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"validSince\" cannot be set when creating a new user.");
638
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"validSince" cannot be set when creating a new user.');
617
639
  }
618
640
  // Throw error when tenantId is passed in POST body.
619
641
  if (typeof request.tenantId !== 'undefined') {
@@ -687,7 +709,7 @@ var LIST_OAUTH_IDP_CONFIGS = new api_request_1.ApiSettings('/oauthIdpConfigs', '
687
709
  if (!validator.isNumber(request.pageSize) ||
688
710
  request.pageSize <= 0 ||
689
711
  request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
690
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive integer that does not exceed " +
712
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
691
713
  (MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
692
714
  }
693
715
  });
@@ -733,7 +755,7 @@ var LIST_INBOUND_SAML_CONFIGS = new api_request_1.ApiSettings('/inboundSamlConfi
733
755
  if (!validator.isNumber(request.pageSize) ||
734
756
  request.pageSize <= 0 ||
735
757
  request.pageSize > MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE) {
736
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive integer that does not exceed " +
758
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive integer that does not exceed ' +
737
759
  (MAX_LIST_PROVIDER_CONFIGURATION_PAGE_SIZE + "."));
738
760
  }
739
761
  });
@@ -750,7 +772,7 @@ var AbstractAuthRequestHandler = /** @class */ (function () {
750
772
  if (typeof app !== 'object' || app === null || !('options' in app)) {
751
773
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.auth() must be a valid Firebase app instance.');
752
774
  }
753
- this.httpClient = new api_request_1.AuthorizedHttpClient(app);
775
+ this.httpClient = new AuthHttpClient(app);
754
776
  }
755
777
  /**
756
778
  * @param {any} response The response to check for errors.
@@ -860,6 +882,18 @@ var AbstractAuthRequestHandler = /** @class */ (function () {
860
882
  };
861
883
  return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
862
884
  };
885
+ AbstractAuthRequestHandler.prototype.getAccountInfoByFederatedUid = function (providerId, rawId) {
886
+ if (!validator.isNonEmptyString(providerId) || !validator.isNonEmptyString(rawId)) {
887
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
888
+ }
889
+ var request = {
890
+ federatedUserId: [{
891
+ providerId: providerId,
892
+ rawId: rawId,
893
+ }],
894
+ };
895
+ return this.invokeRequestHandler(this.getAuthUrlBuilder(), exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
896
+ };
863
897
  /**
864
898
  * Looks up multiple users by their identifiers (uid, email, etc).
865
899
  *
@@ -1048,6 +1082,26 @@ var AbstractAuthRequestHandler = /** @class */ (function () {
1048
1082
  else if (!validator.isNonNullObject(properties)) {
1049
1083
  return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
1050
1084
  }
1085
+ else if (validator.isNonNullObject(properties.providerToLink)) {
1086
+ // TODO(rsgowman): These checks overlap somewhat with
1087
+ // validateProviderUserInfo. It may be possible to refactor a bit.
1088
+ if (!validator.isNonEmptyString(properties.providerToLink.providerId)) {
1089
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.providerId of properties argument must be a non-empty string.');
1090
+ }
1091
+ if (!validator.isNonEmptyString(properties.providerToLink.uid)) {
1092
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providerToLink.uid of properties argument must be a non-empty string.');
1093
+ }
1094
+ }
1095
+ else if (typeof properties.providersToUnlink !== 'undefined') {
1096
+ if (!validator.isArray(properties.providersToUnlink)) {
1097
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
1098
+ }
1099
+ properties.providersToUnlink.forEach(function (providerId) {
1100
+ if (!validator.isNonEmptyString(providerId)) {
1101
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'providersToUnlink of properties argument must be an array of strings.');
1102
+ }
1103
+ });
1104
+ }
1051
1105
  // Build the setAccountInfo request.
1052
1106
  var request = deep_copy_1.deepCopy(properties);
1053
1107
  request.localId = uid;
@@ -1078,14 +1132,22 @@ var AbstractAuthRequestHandler = /** @class */ (function () {
1078
1132
  // It will be removed from the backend request and an additional parameter
1079
1133
  // deleteProvider: ['phone'] with an array of providerIds (phone in this case),
1080
1134
  // will be passed.
1081
- // Currently this applies to phone provider only.
1082
1135
  if (request.phoneNumber === null) {
1083
- request.deleteProvider = ['phone'];
1136
+ request.deleteProvider ? request.deleteProvider.push('phone') : request.deleteProvider = ['phone'];
1084
1137
  delete request.phoneNumber;
1085
1138
  }
1086
- else {
1087
- // Doesn't apply to other providers in admin SDK.
1088
- delete request.deleteProvider;
1139
+ if (typeof (request.providerToLink) !== 'undefined') {
1140
+ request.linkProviderUserInfo = deep_copy_1.deepCopy(request.providerToLink);
1141
+ delete request.providerToLink;
1142
+ request.linkProviderUserInfo.rawId = request.linkProviderUserInfo.uid;
1143
+ delete request.linkProviderUserInfo.uid;
1144
+ }
1145
+ if (typeof (request.providersToUnlink) !== 'undefined') {
1146
+ if (!validator.isArray(request.deleteProvider)) {
1147
+ request.deleteProvider = [];
1148
+ }
1149
+ request.deleteProvider = request.deleteProvider.concat(request.providersToUnlink);
1150
+ delete request.providersToUnlink;
1089
1151
  }
1090
1152
  // Rewrite photoURL to photoUrl.
1091
1153
  if (typeof request.photoURL !== 'undefined') {
@@ -1567,7 +1629,7 @@ var LIST_TENANTS = new api_request_1.ApiSettings('/tenants', 'GET')
1567
1629
  if (!validator.isNumber(request.pageSize) ||
1568
1630
  request.pageSize <= 0 ||
1569
1631
  request.pageSize > MAX_LIST_TENANT_PAGE_SIZE) {
1570
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive non-zero number that does not exceed " +
1632
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Required "maxResults" must be a positive non-zero number that does not exceed ' +
1571
1633
  ("the allowed " + MAX_LIST_TENANT_PAGE_SIZE + "."));
1572
1634
  }
1573
1635
  });
@@ -1783,3 +1845,14 @@ var TenantAwareAuthRequestHandler = /** @class */ (function (_super) {
1783
1845
  return TenantAwareAuthRequestHandler;
1784
1846
  }(AbstractAuthRequestHandler));
1785
1847
  exports.TenantAwareAuthRequestHandler = TenantAwareAuthRequestHandler;
1848
+ function emulatorHost() {
1849
+ return process.env.FIREBASE_AUTH_EMULATOR_HOST;
1850
+ }
1851
+ /**
1852
+ * When true the SDK should communicate with the Auth Emulator for all API
1853
+ * calls and also produce unsigned tokens.
1854
+ */
1855
+ function useEmulator() {
1856
+ return !!emulatorHost();
1857
+ }
1858
+ exports.useEmulator = useEmulator;
@@ -1,4 +1,4 @@
1
- /*! firebase-admin v9.3.0 */
1
+ /*! firebase-admin v9.5.0 */
2
2
  "use strict";
3
3
  /*!
4
4
  * Copyright 2018 Google Inc.
@@ -16,20 +16,20 @@
16
16
  * limitations under the License.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.OIDCConfig = exports.SAMLConfig = exports.EmailSignInConfig = exports.validateTestPhoneNumbers = exports.MultiFactorAuthConfig = exports.AUTH_FACTOR_SERVER_TO_CLIENT_TYPE = exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE = exports.MAXIMUM_TEST_PHONE_NUMBERS = void 0;
19
+ exports.OIDCConfig = exports.SAMLConfig = exports.EmailSignInConfig = exports.validateTestPhoneNumbers = exports.MultiFactorAuthConfig = exports.MAXIMUM_TEST_PHONE_NUMBERS = void 0;
20
20
  var validator = require("../utils/validator");
21
21
  var deep_copy_1 = require("../utils/deep-copy");
22
22
  var error_1 = require("../utils/error");
23
23
  /** A maximum of 10 test phone number / code pairs can be configured. */
24
24
  exports.MAXIMUM_TEST_PHONE_NUMBERS = 10;
25
25
  /** Client Auth factor type to server auth factor type mapping. */
26
- exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE = {
26
+ var AUTH_FACTOR_CLIENT_TO_SERVER_TYPE = {
27
27
  phone: 'PHONE_SMS',
28
28
  };
29
29
  /** Server Auth factor type to client auth factor type mapping. */
30
- exports.AUTH_FACTOR_SERVER_TO_CLIENT_TYPE = Object.keys(exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE)
30
+ var AUTH_FACTOR_SERVER_TO_CLIENT_TYPE = Object.keys(AUTH_FACTOR_CLIENT_TO_SERVER_TYPE)
31
31
  .reduce(function (res, key) {
32
- res[exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[key]] = key;
32
+ res[AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[key]] = key;
33
33
  return res;
34
34
  }, {});
35
35
  /**
@@ -54,8 +54,8 @@ var MultiFactorAuthConfig = /** @class */ (function () {
54
54
  (response.enabledProviders || []).forEach(function (enabledProvider) {
55
55
  // Ignore unsupported types. It is possible the current admin SDK version is
56
56
  // not up to date and newer backend types are supported.
57
- if (typeof exports.AUTH_FACTOR_SERVER_TO_CLIENT_TYPE[enabledProvider] !== 'undefined') {
58
- _this.factorIds.push(exports.AUTH_FACTOR_SERVER_TO_CLIENT_TYPE[enabledProvider]);
57
+ if (typeof AUTH_FACTOR_SERVER_TO_CLIENT_TYPE[enabledProvider] !== 'undefined') {
58
+ _this.factorIds.push(AUTH_FACTOR_SERVER_TO_CLIENT_TYPE[enabledProvider]);
59
59
  }
60
60
  });
61
61
  }
@@ -77,7 +77,7 @@ var MultiFactorAuthConfig = /** @class */ (function () {
77
77
  if (typeof request.enabledProviders === 'undefined') {
78
78
  request.enabledProviders = [];
79
79
  }
80
- request.enabledProviders.push(exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[factorId]);
80
+ request.enabledProviders.push(AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[factorId]);
81
81
  });
82
82
  // In case an empty array is passed. Ensure it gets populated so the array is cleared.
83
83
  if (options.factorIds && options.factorIds.length === 0) {
@@ -117,7 +117,7 @@ var MultiFactorAuthConfig = /** @class */ (function () {
117
117
  }
118
118
  // Validate content of array.
119
119
  options.factorIds.forEach(function (factorId) {
120
- if (typeof exports.AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[factorId] === 'undefined') {
120
+ if (typeof AUTH_FACTOR_CLIENT_TO_SERVER_TYPE[factorId] === 'undefined') {
121
121
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONFIG, "\"" + factorId + "\" is not a valid \"AuthFactorType\".");
122
122
  }
123
123
  });
@@ -425,7 +425,7 @@ var SAMLConfig = /** @class */ (function () {
425
425
  throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONFIG, '"SAMLAuthProviderConfig.displayName" must be a valid string.');
426
426
  }
427
427
  };
428
- /** @return {SAMLAuthProviderConfig} The plain object representation of the SAMLConfig. */
428
+ /** @return The plain object representation of the SAMLConfig. */
429
429
  SAMLConfig.prototype.toJSON = function () {
430
430
  return {
431
431
  enabled: this.enabled,
@@ -479,9 +479,9 @@ var OIDCConfig = /** @class */ (function () {
479
479
  * Throws an error if validation fails. If the request is not a OIDCConfig request,
480
480
  * returns null.
481
481
  *
482
- * @param {OIDCAuthProviderRequest} options The options object to convert to a server request.
483
- * @param {boolean=} ignoreMissingFields Whether to ignore missing fields.
484
- * @return {?OIDCConfigServerRequest} The resulting server request or null if not valid.
482
+ * @param options The options object to convert to a server request.
483
+ * @param ignoreMissingFields Whether to ignore missing fields.
484
+ * @return The resulting server request or null if not valid.
485
485
  */
486
486
  OIDCConfig.buildServerRequest = function (options, ignoreMissingFields) {
487
487
  if (ignoreMissingFields === void 0) { ignoreMissingFields = false; }
@@ -523,8 +523,8 @@ var OIDCConfig = /** @class */ (function () {
523
523
  /**
524
524
  * Validates the OIDCConfig options object. Throws an error on failure.
525
525
  *
526
- * @param {OIDCAuthProviderRequest} options The options object to validate.
527
- * @param {boolean=} ignoreMissingFields Whether to ignore missing fields.
526
+ * @param options The options object to validate.
527
+ * @param ignoreMissingFields Whether to ignore missing fields.
528
528
  */
529
529
  OIDCConfig.validate = function (options, ignoreMissingFields) {
530
530
  if (ignoreMissingFields === void 0) { ignoreMissingFields = false; }
package/lib/auth/auth.js CHANGED
@@ -1,6 +1,7 @@
1
- /*! firebase-admin v9.3.0 */
1
+ /*! firebase-admin v9.5.0 */
2
2
  "use strict";
3
3
  /*!
4
+ * @license
4
5
  * Copyright 2017 Google Inc.
5
6
  *
6
7
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,6 +31,7 @@ var __extends = (this && this.__extends) || (function () {
30
31
  })();
31
32
  Object.defineProperty(exports, "__esModule", { value: true });
32
33
  exports.Auth = exports.TenantAwareAuth = exports.BaseAuth = void 0;
34
+ var deep_copy_1 = require("../utils/deep-copy");
33
35
  var user_record_1 = require("./user-record");
34
36
  var identifier_1 = require("./identifier");
35
37
  var token_generator_1 = require("./token-generator");
@@ -40,23 +42,6 @@ var validator = require("../utils/validator");
40
42
  var token_verifier_1 = require("./token-verifier");
41
43
  var auth_config_1 = require("./auth-config");
42
44
  var tenant_manager_1 = require("./tenant-manager");
43
- /**
44
- * Internals of an Auth instance.
45
- */
46
- var AuthInternals = /** @class */ (function () {
47
- function AuthInternals() {
48
- }
49
- /**
50
- * Deletes the service and its associated resources.
51
- *
52
- * @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
53
- */
54
- AuthInternals.prototype.delete = function () {
55
- // There are no resources to clean up
56
- return Promise.resolve(undefined);
57
- };
58
- return AuthInternals;
59
- }());
60
45
  /**
61
46
  * Base Auth class. Mainly used for user management APIs.
62
47
  */
@@ -77,7 +62,7 @@ var BaseAuth = /** @class */ (function () {
77
62
  this.tokenGenerator = tokenGenerator;
78
63
  }
79
64
  else {
80
- var cryptoSigner = useEmulator() ? new token_generator_1.EmulatedSigner() : token_generator_1.cryptoSignerFromApp(app);
65
+ var cryptoSigner = auth_api_request_1.useEmulator() ? new token_generator_1.EmulatedSigner() : token_generator_1.cryptoSignerFromApp(app);
81
66
  this.tokenGenerator = new token_generator_1.FirebaseTokenGenerator(cryptoSigner);
82
67
  }
83
68
  this.sessionCookieVerifier = token_verifier_1.createSessionCookieVerifier(app);
@@ -110,13 +95,14 @@ var BaseAuth = /** @class */ (function () {
110
95
  BaseAuth.prototype.verifyIdToken = function (idToken, checkRevoked) {
111
96
  var _this = this;
112
97
  if (checkRevoked === void 0) { checkRevoked = false; }
113
- return this.idTokenVerifier.verifyJWT(idToken)
98
+ var isEmulator = auth_api_request_1.useEmulator();
99
+ return this.idTokenVerifier.verifyJWT(idToken, isEmulator)
114
100
  .then(function (decodedIdToken) {
115
101
  // Whether to check if the token was revoked.
116
- if (!checkRevoked) {
117
- return decodedIdToken;
102
+ if (checkRevoked || isEmulator) {
103
+ return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.ID_TOKEN_REVOKED);
118
104
  }
119
- return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.ID_TOKEN_REVOKED);
105
+ return decodedIdToken;
120
106
  });
121
107
  };
122
108
  /**
@@ -161,6 +147,35 @@ var BaseAuth = /** @class */ (function () {
161
147
  return new user_record_1.UserRecord(response.users[0]);
162
148
  });
163
149
  };
150
+ /**
151
+ * Gets the user data for the user corresponding to a given provider id.
152
+ *
153
+ * See [Retrieve user data](/docs/auth/admin/manage-users#retrieve_user_data)
154
+ * for code samples and detailed documentation.
155
+ *
156
+ * @param providerId The provider ID, for example, "google.com" for the
157
+ * Google provider.
158
+ * @param uid The user identifier for the given provider.
159
+ *
160
+ * @return A promise fulfilled with the user data corresponding to the
161
+ * given provider id.
162
+ */
163
+ BaseAuth.prototype.getUserByProviderUid = function (providerId, uid) {
164
+ // Although we don't really advertise it, we want to also handle
165
+ // non-federated idps with this call. So if we detect one of them, we'll
166
+ // reroute this request appropriately.
167
+ if (providerId === 'phone') {
168
+ return this.getUserByPhoneNumber(uid);
169
+ }
170
+ else if (providerId === 'email') {
171
+ return this.getUserByEmail(uid);
172
+ }
173
+ return this.authRequestHandler.getAccountInfoByFederatedUid(providerId, uid)
174
+ .then(function (response) {
175
+ // Returns the user record populated with server response.
176
+ return new user_record_1.UserRecord(response.users[0]);
177
+ });
178
+ };
164
179
  /**
165
180
  * Gets the user data corresponding to the specified identifiers.
166
181
  *
@@ -325,6 +340,43 @@ var BaseAuth = /** @class */ (function () {
325
340
  */
326
341
  BaseAuth.prototype.updateUser = function (uid, properties) {
327
342
  var _this = this;
343
+ // Although we don't really advertise it, we want to also handle linking of
344
+ // non-federated idps with this call. So if we detect one of them, we'll
345
+ // adjust the properties parameter appropriately. This *does* imply that a
346
+ // conflict could arise, e.g. if the user provides a phoneNumber property,
347
+ // but also provides a providerToLink with a 'phone' provider id. In that
348
+ // case, we'll throw an error.
349
+ properties = deep_copy_1.deepCopy(properties);
350
+ if (properties === null || properties === void 0 ? void 0 : properties.providerToLink) {
351
+ if (properties.providerToLink.providerId === 'email') {
352
+ if (typeof properties.email !== 'undefined') {
353
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.email and UpdateRequest.providerToLink.providerId='email' were set. To "
354
+ + 'link to the email/password provider, only specify the UpdateRequest.email field.');
355
+ }
356
+ properties.email = properties.providerToLink.uid;
357
+ delete properties.providerToLink;
358
+ }
359
+ else if (properties.providerToLink.providerId === 'phone') {
360
+ if (typeof properties.phoneNumber !== 'undefined') {
361
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.phoneNumber and UpdateRequest.providerToLink.providerId='phone' were set. To "
362
+ + 'link to a phone provider, only specify the UpdateRequest.phoneNumber field.');
363
+ }
364
+ properties.phoneNumber = properties.providerToLink.uid;
365
+ delete properties.providerToLink;
366
+ }
367
+ }
368
+ if (properties === null || properties === void 0 ? void 0 : properties.providersToUnlink) {
369
+ if (properties.providersToUnlink.indexOf('phone') !== -1) {
370
+ // If we've been told to unlink the phone provider both via setting
371
+ // phoneNumber to null *and* by setting providersToUnlink to include
372
+ // 'phone', then we'll reject that. Though it might also be reasonable
373
+ // to relax this restriction and just unlink it.
374
+ if (properties.phoneNumber === null) {
375
+ throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.phoneNumber=null and UpdateRequest.providersToUnlink=['phone'] were set. To "
376
+ + 'unlink from a phone provider, only specify the UpdateRequest.phoneNumber=null field.');
377
+ }
378
+ }
379
+ }
328
380
  return this.authRequestHandler.updateExistingAccount(uid, properties)
329
381
  .then(function (existingUid) {
330
382
  // Return the corresponding user record.
@@ -411,13 +463,14 @@ var BaseAuth = /** @class */ (function () {
411
463
  BaseAuth.prototype.verifySessionCookie = function (sessionCookie, checkRevoked) {
412
464
  var _this = this;
413
465
  if (checkRevoked === void 0) { checkRevoked = false; }
414
- return this.sessionCookieVerifier.verifyJWT(sessionCookie)
466
+ var isEmulator = auth_api_request_1.useEmulator();
467
+ return this.sessionCookieVerifier.verifyJWT(sessionCookie, isEmulator)
415
468
  .then(function (decodedIdToken) {
416
469
  // Whether to check if the token was revoked.
417
- if (!checkRevoked) {
418
- return decodedIdToken;
470
+ if (checkRevoked || isEmulator) {
471
+ return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.SESSION_COOKIE_REVOKED);
419
472
  }
420
- return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.SESSION_COOKIE_REVOKED);
473
+ return decodedIdToken;
421
474
  });
422
475
  };
423
476
  /**
@@ -508,7 +561,7 @@ var BaseAuth = /** @class */ (function () {
508
561
  return processResponse(response, providerConfigs);
509
562
  });
510
563
  }
511
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"AuthProviderConfigFilter.type\" must be either \"saml' or \"oidc\""));
564
+ return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"AuthProviderConfigFilter.type" must be either "saml" or "oidc"'));
512
565
  };
513
566
  /**
514
567
  * Looks up an Auth provider configuration by ID.
@@ -626,26 +679,6 @@ var BaseAuth = /** @class */ (function () {
626
679
  return decodedIdToken;
627
680
  });
628
681
  };
629
- /**
630
- * Enable or disable ID token verification. This is used to safely short-circuit token verification with the
631
- * Auth emulator. When disabled ONLY unsigned tokens will pass verification, production tokens will not pass.
632
- *
633
- * WARNING: This is a dangerous method that will compromise your app's security and break your app in
634
- * production. Developers should never call this method, it is for internal testing use only.
635
- *
636
- * @internal
637
- */
638
- // @ts-expect-error: this method appears unused but is used privately.
639
- BaseAuth.prototype.setJwtVerificationEnabled = function (enabled) {
640
- if (!enabled && !useEmulator()) {
641
- // We only allow verification to be disabled in conjunction with
642
- // the emulator environment variable.
643
- throw new Error('This method is only available when connected to the Authentication emulator.');
644
- }
645
- var algorithm = enabled ? token_verifier_1.ALGORITHM_RS256 : 'none';
646
- this.idTokenVerifier.setAlgorithm(algorithm);
647
- this.sessionCookieVerifier.setAlgorithm(algorithm);
648
- };
649
682
  return BaseAuth;
650
683
  }());
651
684
  exports.BaseAuth = BaseAuth;
@@ -663,7 +696,7 @@ var TenantAwareAuth = /** @class */ (function (_super) {
663
696
  */
664
697
  function TenantAwareAuth(app, tenantId) {
665
698
  var _this = this;
666
- var cryptoSigner = useEmulator() ? new token_generator_1.EmulatedSigner() : token_generator_1.cryptoSignerFromApp(app);
699
+ var cryptoSigner = auth_api_request_1.useEmulator() ? new token_generator_1.EmulatedSigner() : token_generator_1.cryptoSignerFromApp(app);
667
700
  var tokenGenerator = new token_generator_1.FirebaseTokenGenerator(cryptoSigner, tenantId);
668
701
  _this = _super.call(this, app, new auth_api_request_1.TenantAwareAuthRequestHandler(app, tenantId), tokenGenerator) || this;
669
702
  utils.addReadonlyGetter(_this, 'tenantId', tenantId);
@@ -758,7 +791,6 @@ var Auth = /** @class */ (function (_super) {
758
791
  */
759
792
  function Auth(app) {
760
793
  var _this = _super.call(this, app, new auth_api_request_1.AuthRequestHandler(app)) || this;
761
- _this.INTERNAL = new AuthInternals();
762
794
  _this.app_ = app;
763
795
  _this.tenantManager_ = new tenant_manager_1.TenantManager(app);
764
796
  return _this;
@@ -782,14 +814,3 @@ var Auth = /** @class */ (function (_super) {
782
814
  return Auth;
783
815
  }(BaseAuth));
784
816
  exports.Auth = Auth;
785
- /**
786
- * When true the SDK should communicate with the Auth Emulator for all API
787
- * calls and also produce unsigned tokens.
788
- *
789
- * This alone does <b>NOT<b> short-circuit ID Token verification.
790
- * For security reasons that must be explicitly disabled through
791
- * setJwtVerificationEnabled(false);
792
- */
793
- function useEmulator() {
794
- return !!process.env.FIREBASE_AUTH_EMULATOR_HOST;
795
- }
@@ -1,4 +1,4 @@
1
- /*! firebase-admin v9.3.0 */
1
+ /*! firebase-admin v9.5.0 */
2
2
  "use strict";
3
3
  /*!
4
4
  * Copyright 2020 Google Inc.
@@ -17,7 +17,8 @@
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.isProviderIdentifier = exports.isPhoneIdentifier = exports.isEmailIdentifier = exports.isUidIdentifier = void 0;
20
- /* User defined type guards. See
20
+ /*
21
+ * User defined type guards. See
21
22
  * https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
22
23
  */
23
24
  function isUidIdentifier(id) {