firebase-tools 11.0.1 → 11.2.1

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 (214) hide show
  1. package/lib/accountExporter.js +11 -4
  2. package/lib/accountImporter.js +93 -95
  3. package/lib/api.js +77 -218
  4. package/lib/apiv2.js +5 -4
  5. package/lib/appdistribution/client.js +7 -9
  6. package/lib/auth.js +72 -52
  7. package/lib/bin/firebase.js +42 -47
  8. package/lib/checkValidTargetFilters.js +36 -25
  9. package/lib/commands/appdistribution-distribute.js +2 -1
  10. package/lib/commands/appdistribution-testers-add.js +2 -1
  11. package/lib/commands/appdistribution-testers-remove.js +2 -1
  12. package/lib/commands/apps-android-sha-create.js +2 -1
  13. package/lib/commands/apps-android-sha-delete.js +2 -1
  14. package/lib/commands/apps-android-sha-list.js +2 -1
  15. package/lib/commands/apps-create.js +2 -1
  16. package/lib/commands/apps-list.js +2 -1
  17. package/lib/commands/apps-sdkconfig.js +2 -1
  18. package/lib/commands/auth-export.js +2 -1
  19. package/lib/commands/auth-import.js +7 -10
  20. package/lib/commands/crashlytics-symbols-upload.js +2 -1
  21. package/lib/commands/database-get.js +4 -3
  22. package/lib/commands/database-instances-create.js +2 -1
  23. package/lib/commands/database-instances-list.js +3 -3
  24. package/lib/commands/database-profile.js +4 -4
  25. package/lib/commands/database-push.js +4 -4
  26. package/lib/commands/database-remove.js +3 -3
  27. package/lib/commands/database-rules-canary.js +2 -1
  28. package/lib/commands/database-rules-get.js +2 -1
  29. package/lib/commands/database-rules-list.js +2 -1
  30. package/lib/commands/database-rules-release.js +2 -1
  31. package/lib/commands/database-rules-stage.js +2 -1
  32. package/lib/commands/database-set.js +3 -3
  33. package/lib/commands/database-settings-get.js +2 -1
  34. package/lib/commands/database-settings-set.js +2 -1
  35. package/lib/commands/database-update.js +2 -1
  36. package/lib/commands/deploy.js +26 -25
  37. package/lib/commands/emulators-exec.js +2 -1
  38. package/lib/commands/emulators-export.js +2 -1
  39. package/lib/commands/emulators-start.js +2 -1
  40. package/lib/commands/experimental-functions-shell.js +10 -8
  41. package/lib/commands/ext-configure.js +2 -1
  42. package/lib/commands/ext-dev-deprecate.js +2 -1
  43. package/lib/commands/ext-dev-emulators-exec.js +3 -2
  44. package/lib/commands/ext-dev-emulators-start.js +3 -2
  45. package/lib/commands/ext-dev-extension-delete.js +2 -1
  46. package/lib/commands/ext-dev-init.js +2 -1
  47. package/lib/commands/ext-dev-list.js +8 -8
  48. package/lib/commands/ext-dev-publish.js +2 -1
  49. package/lib/commands/ext-dev-register.js +2 -1
  50. package/lib/commands/ext-dev-undeprecate.js +2 -1
  51. package/lib/commands/ext-dev-unpublish.js +2 -1
  52. package/lib/commands/ext-dev-usage.js +2 -1
  53. package/lib/commands/ext-export.js +2 -1
  54. package/lib/commands/ext-info.js +14 -14
  55. package/lib/commands/ext-install.js +2 -1
  56. package/lib/commands/ext-list.js +2 -1
  57. package/lib/commands/ext-sources-create.js +2 -1
  58. package/lib/commands/ext-uninstall.js +2 -1
  59. package/lib/commands/ext-update.js +2 -1
  60. package/lib/commands/ext.js +4 -4
  61. package/lib/commands/firestore-delete.js +2 -1
  62. package/lib/commands/firestore-indexes-list.js +2 -1
  63. package/lib/commands/functions-config-clone.js +4 -3
  64. package/lib/commands/functions-config-export.js +2 -1
  65. package/lib/commands/functions-config-get.js +2 -1
  66. package/lib/commands/functions-config-set.js +2 -1
  67. package/lib/commands/functions-config-unset.js +2 -1
  68. package/lib/commands/functions-delete.js +3 -8
  69. package/lib/commands/functions-deletegcfartifacts.js +2 -1
  70. package/lib/commands/functions-list.js +2 -1
  71. package/lib/commands/functions-log.js +2 -1
  72. package/lib/commands/functions-secrets-access.js +2 -1
  73. package/lib/commands/functions-secrets-destroy.js +2 -1
  74. package/lib/commands/functions-secrets-get.js +2 -1
  75. package/lib/commands/functions-secrets-prune.js +2 -1
  76. package/lib/commands/functions-secrets-set.js +2 -1
  77. package/lib/commands/functions-shell.js +12 -10
  78. package/lib/commands/help.js +2 -1
  79. package/lib/commands/hosting-channel-create.js +2 -1
  80. package/lib/commands/hosting-channel-delete.js +2 -1
  81. package/lib/commands/hosting-channel-deploy.js +2 -1
  82. package/lib/commands/hosting-channel-list.js +2 -1
  83. package/lib/commands/hosting-channel-open.js +2 -1
  84. package/lib/commands/hosting-clone.js +2 -1
  85. package/lib/commands/hosting-disable.js +2 -1
  86. package/lib/commands/hosting-sites-create.js +2 -1
  87. package/lib/commands/hosting-sites-delete.js +2 -1
  88. package/lib/commands/hosting-sites-get.js +2 -1
  89. package/lib/commands/hosting-sites-list.js +2 -1
  90. package/lib/commands/index.js +23 -13
  91. package/lib/commands/init.js +47 -43
  92. package/lib/commands/login-add.js +2 -1
  93. package/lib/commands/login-ci.js +2 -1
  94. package/lib/commands/login-list.js +2 -1
  95. package/lib/commands/login-use.js +2 -1
  96. package/lib/commands/login.js +2 -1
  97. package/lib/commands/logout.js +2 -1
  98. package/lib/commands/open.js +7 -7
  99. package/lib/commands/projects-addfirebase.js +2 -1
  100. package/lib/commands/projects-create.js +2 -1
  101. package/lib/commands/projects-list.js +2 -1
  102. package/lib/commands/remoteconfig-get.js +2 -1
  103. package/lib/commands/remoteconfig-rollback.js +2 -1
  104. package/lib/commands/remoteconfig-versions-list.js +2 -1
  105. package/lib/commands/serve.js +30 -30
  106. package/lib/commands/setup-emulators-database.js +2 -1
  107. package/lib/commands/setup-emulators-firestore.js +2 -1
  108. package/lib/commands/setup-emulators-pubsub.js +2 -1
  109. package/lib/commands/setup-emulators-storage.js +2 -1
  110. package/lib/commands/setup-emulators-ui.js +2 -1
  111. package/lib/commands/target-apply.js +2 -1
  112. package/lib/commands/target-clear.js +2 -1
  113. package/lib/commands/target-remove.js +2 -1
  114. package/lib/commands/target.js +2 -1
  115. package/lib/commands/use.js +54 -53
  116. package/lib/config.js +7 -6
  117. package/lib/deploy/database/deploy.js +3 -2
  118. package/lib/deploy/database/index.js +8 -5
  119. package/lib/deploy/database/prepare.js +22 -20
  120. package/lib/deploy/database/release.js +12 -9
  121. package/lib/deploy/extensions/secrets.js +3 -3
  122. package/lib/deploy/firestore/prepare.js +2 -2
  123. package/lib/deploy/functions/build.js +33 -20
  124. package/lib/deploy/functions/ensure.js +1 -11
  125. package/lib/deploy/functions/prepare.js +3 -13
  126. package/lib/deploy/functions/prepareFunctionsUpload.js +2 -3
  127. package/lib/deploy/functions/release/fabricator.js +0 -1
  128. package/lib/deploy/functions/release/index.js +1 -5
  129. package/lib/deploy/functions/runtimes/discovery/index.js +18 -3
  130. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +188 -54
  131. package/lib/deploy/functions/runtimes/golang/index.js +2 -22
  132. package/lib/deploy/functions/runtimes/node/index.js +3 -7
  133. package/lib/deploy/functions/runtimes/node/parseTriggers.js +16 -4
  134. package/lib/deploy/functions/services/database.js +14 -0
  135. package/lib/deploy/functions/services/index.js +14 -0
  136. package/lib/deploy/index.js +3 -3
  137. package/lib/deploy/lifecycleHooks.js +27 -27
  138. package/lib/deploy/remoteconfig/prepare.js +2 -2
  139. package/lib/deploy/storage/prepare.js +1 -1
  140. package/lib/emulator/auth/apiSpec.js +14 -46
  141. package/lib/emulator/auth/index.js +1 -1
  142. package/lib/emulator/auth/operations.js +342 -93
  143. package/lib/emulator/auth/server.js +2 -2
  144. package/lib/emulator/auth/state.js +34 -32
  145. package/lib/emulator/commandUtils.js +1 -1
  146. package/lib/emulator/constants.js +1 -1
  147. package/lib/emulator/controller.js +7 -6
  148. package/lib/emulator/databaseEmulator.js +4 -4
  149. package/lib/emulator/download.js +1 -1
  150. package/lib/emulator/downloadableEmulators.js +5 -5
  151. package/lib/emulator/events/types.js +2 -3
  152. package/lib/emulator/firestoreEmulator.js +2 -2
  153. package/lib/emulator/functionsEmulator.js +31 -45
  154. package/lib/emulator/functionsEmulatorRuntime.js +12 -16
  155. package/lib/emulator/functionsEmulatorShared.js +7 -5
  156. package/lib/emulator/functionsRuntimeWorker.js +0 -6
  157. package/lib/emulator/hostingEmulator.js +1 -1
  158. package/lib/emulator/hub.js +1 -1
  159. package/lib/emulator/loggingEmulator.js +1 -1
  160. package/lib/emulator/pubsubEmulator.js +1 -1
  161. package/lib/emulator/storage/crc.js +4 -4
  162. package/lib/emulator/storage/index.js +1 -1
  163. package/lib/emulator/types.js +1 -1
  164. package/lib/errorOut.js +2 -2
  165. package/lib/extensions/askUserForConsent.js +1 -2
  166. package/lib/extensions/askUserForParam.js +15 -18
  167. package/lib/extensions/emulator/optionsHelper.js +4 -4
  168. package/lib/extensions/extensionsApi.js +1 -22
  169. package/lib/extensions/extensionsHelper.js +6 -6
  170. package/lib/extensions/listExtensions.js +9 -10
  171. package/lib/extensions/manifest.js +2 -2
  172. package/lib/extensions/resolveSource.js +11 -7
  173. package/lib/extensions/secretsUtils.js +3 -3
  174. package/lib/extensions/types.js +24 -0
  175. package/lib/extensions/updateHelper.js +1 -1
  176. package/lib/extensions/utils.js +1 -2
  177. package/lib/extensions/warnings.js +3 -3
  178. package/lib/firestore/encodeFirestoreValue.js +11 -8
  179. package/lib/fsAsync.js +3 -3
  180. package/lib/functions/events/v2.js +7 -1
  181. package/lib/functionsConfig.js +17 -14
  182. package/lib/functionsConfigClone.js +46 -46
  183. package/lib/gcp/cloudfunctions.js +2 -15
  184. package/lib/gcp/cloudfunctionsv2.js +17 -2
  185. package/lib/gcp/iam.js +1 -1
  186. package/lib/gcp/index.js +10 -10
  187. package/lib/gcp/rules.js +1 -1
  188. package/lib/gcp/runtimeconfig.js +45 -47
  189. package/lib/hosting/proxy.js +1 -1
  190. package/lib/index.js +29 -28
  191. package/lib/init/features/database.js +10 -2
  192. package/lib/init/features/functions/index.js +1 -1
  193. package/lib/init/features/functions/javascript.js +23 -20
  194. package/lib/init/features/functions/npm-dependencies.js +17 -14
  195. package/lib/init/features/functions/typescript.js +27 -24
  196. package/lib/init/features/hosting/github.js +6 -5
  197. package/lib/init/features/hosting/index.js +2 -2
  198. package/lib/loadCJSON.js +9 -6
  199. package/lib/localFunction.js +4 -4
  200. package/lib/logError.js +15 -12
  201. package/lib/parseBoltRules.js +15 -14
  202. package/lib/previews.js +1 -1
  203. package/lib/profileReport.js +504 -512
  204. package/lib/profiler.js +4 -4
  205. package/lib/prompt.js +1 -2
  206. package/lib/rc.js +1 -1
  207. package/lib/requireAuth.js +0 -1
  208. package/lib/responseToError.js +8 -5
  209. package/lib/rulesDeploy.js +2 -2
  210. package/lib/scopes.js +9 -9
  211. package/lib/serve/index.js +4 -5
  212. package/lib/utils.js +30 -6
  213. package/npm-shrinkwrap.json +537 -193
  214. package/package.json +17 -14
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setAccountInfoImpl = exports.resetPassword = exports.SESSION_COOKIE_MAX_VALID_DURATION = exports.CUSTOM_TOKEN_AUDIENCE = exports.authOperations = void 0;
3
+ exports.parseBlockingFunctionJwt = exports.setAccountInfoImpl = exports.resetPassword = exports.SESSION_COOKIE_MAX_VALID_DURATION = exports.CUSTOM_TOKEN_AUDIENCE = exports.authOperations = void 0;
4
4
  const url_1 = require("url");
5
5
  const jsonwebtoken_1 = require("jsonwebtoken");
6
+ const node_fetch_1 = require("node-fetch");
7
+ const abort_controller_1 = require("abort-controller");
6
8
  const utils_1 = require("./utils");
7
9
  const errors_1 = require("./errors");
8
10
  const types_1 = require("../types");
@@ -102,13 +104,13 @@ const MFA_INELIGIBLE_PROVIDER = new Set([
102
104
  state_1.PROVIDER_CUSTOM,
103
105
  state_1.PROVIDER_GAME_CENTER,
104
106
  ]);
105
- function signUp(state, reqBody, ctx) {
106
- var _a;
107
+ async function signUp(state, reqBody, ctx) {
108
+ var _a, _b, _c, _d;
107
109
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
108
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
109
110
  let provider;
110
- const updates = {
111
- lastLoginAt: Date.now().toString(),
111
+ const timestamp = new Date();
112
+ let updates = {
113
+ lastLoginAt: timestamp.getTime().toString(),
112
114
  };
113
115
  if ((_a = ctx.security) === null || _a === void 0 ? void 0 : _a.Oauth2) {
114
116
  if (reqBody.idToken) {
@@ -169,19 +171,31 @@ function signUp(state, reqBody, ctx) {
169
171
  if (reqBody.idToken) {
170
172
  ({ user } = parseIdToken(state, reqBody.idToken));
171
173
  }
174
+ let extraClaims;
172
175
  if (!user) {
173
- if (reqBody.localId) {
174
- user = state.createUserWithLocalId(reqBody.localId, updates);
175
- (0, errors_1.assert)(user, "DUPLICATE_LOCAL_ID");
176
+ updates.createdAt = timestamp.getTime().toString();
177
+ const localId = (_b = reqBody.localId) !== null && _b !== void 0 ? _b : state.generateLocalId();
178
+ if (reqBody.email && !((_c = ctx.security) === null || _c === void 0 ? void 0 : _c.Oauth2)) {
179
+ const userBeforeCreate = Object.assign({ localId }, updates);
180
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "password" });
181
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
176
182
  }
177
- else {
178
- user = state.createUser(updates);
183
+ user = state.createUserWithLocalId(localId, updates);
184
+ (0, errors_1.assert)(user, "DUPLICATE_LOCAL_ID");
185
+ if (reqBody.email && !((_d = ctx.security) === null || _d === void 0 ? void 0 : _d.Oauth2)) {
186
+ if (!user.disabled) {
187
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "password" });
188
+ updates = blockingResponse.updates;
189
+ extraClaims = blockingResponse.extraClaims;
190
+ user = state.updateUserByLocalId(user.localId, updates);
191
+ }
192
+ (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
179
193
  }
180
194
  }
181
195
  else {
182
196
  user = state.updateUserByLocalId(user.localId, updates);
183
197
  }
184
- return Object.assign({ kind: "identitytoolkit#SignupNewUserResponse", localId: user.localId, displayName: user.displayName, email: user.email }, (provider ? issueTokens(state, user, provider) : {}));
198
+ return Object.assign({ kind: "identitytoolkit#SignupNewUserResponse", localId: user.localId, displayName: user.displayName, email: user.email }, (provider ? issueTokens(state, user, provider, { extraClaims }) : {}));
185
199
  }
186
200
  function lookup(state, reqBody, ctx) {
187
201
  var _a, _b, _c, _d, _e;
@@ -227,7 +241,6 @@ function lookup(state, reqBody, ctx) {
227
241
  function batchCreate(state, reqBody) {
228
242
  var _a, _b;
229
243
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
230
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
231
244
  (0, errors_1.assert)((_a = reqBody.users) === null || _a === void 0 ? void 0 : _a.length, "MISSING_USER_ACCOUNT");
232
245
  if (reqBody.sanityCheck) {
233
246
  if (state.oneAccountPerEmail) {
@@ -423,7 +436,6 @@ function batchGet(state, reqBody, ctx) {
423
436
  function createAuthUri(state, reqBody) {
424
437
  var _a;
425
438
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
426
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
427
439
  const sessionId = reqBody.sessionId || (0, utils_1.randomId)(27);
428
440
  if (reqBody.providerId) {
429
441
  throw new errors_1.NotImplementedError("Sign-in with IDP is not yet supported.");
@@ -482,8 +494,7 @@ function createAuthUri(state, reqBody) {
482
494
  }
483
495
  const SESSION_COOKIE_MIN_VALID_DURATION = 5 * 60;
484
496
  exports.SESSION_COOKIE_MAX_VALID_DURATION = 14 * 24 * 60 * 60;
485
- function createSessionCookie(state, reqBody, ctx) {
486
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
497
+ function createSessionCookie(state, reqBody) {
487
498
  (0, errors_1.assert)(reqBody.idToken, "MISSING_ID_TOKEN");
488
499
  const validDuration = Number(reqBody.validDuration) || exports.SESSION_COOKIE_MAX_VALID_DURATION;
489
500
  (0, errors_1.assert)(validDuration >= SESSION_COOKIE_MIN_VALID_DURATION &&
@@ -573,7 +584,6 @@ function queryAccounts(state, reqBody) {
573
584
  function resetPassword(state, reqBody) {
574
585
  var _a;
575
586
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
576
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
577
587
  (0, errors_1.assert)(state.allowPasswordSignup, "PASSWORD_LOGIN_DISABLED");
578
588
  (0, errors_1.assert)(reqBody.oobCode, "MISSING_OOB_CODE");
579
589
  const oob = state.validateOobCode(reqBody.oobCode);
@@ -604,7 +614,6 @@ exports.resetPassword = resetPassword;
604
614
  function sendOobCode(state, reqBody, ctx) {
605
615
  var _a;
606
616
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
607
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
608
617
  (0, errors_1.assert)(reqBody.requestType && reqBody.requestType !== "OOB_REQ_TYPE_UNSPECIFIED", "MISSING_REQ_TYPE");
609
618
  if (reqBody.returnOobLink) {
610
619
  (0, errors_1.assert)((_a = ctx.security) === null || _a === void 0 ? void 0 : _a.Oauth2, "INSUFFICIENT_PERMISSION");
@@ -673,7 +682,6 @@ function sendVerificationCode(state, reqBody) {
673
682
  var _a;
674
683
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
675
684
  (0, errors_1.assert)(state instanceof state_1.AgentProjectState, "UNSUPPORTED_TENANT_OPERATION");
676
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
677
685
  (0, errors_1.assert)(reqBody.phoneNumber && (0, utils_1.isValidPhoneNumber)(reqBody.phoneNumber), "INVALID_PHONE_NUMBER : Invalid format.");
678
686
  const user = state.getUserByPhoneNumber(reqBody.phoneNumber);
679
687
  (0, errors_1.assert)(!((_a = user === null || user === void 0 ? void 0 : user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length), "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
@@ -686,7 +694,6 @@ function sendVerificationCode(state, reqBody) {
686
694
  function setAccountInfo(state, reqBody, ctx) {
687
695
  var _a;
688
696
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
689
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
690
697
  const url = (0, utils_1.authEmulatorUrl)(ctx.req);
691
698
  return setAccountInfoImpl(state, reqBody, {
692
699
  privileged: !!((_a = ctx.security) === null || _a === void 0 ? void 0 : _a.Oauth2),
@@ -943,10 +950,11 @@ function signInWithCustomToken(state, reqBody) {
943
950
  extraClaims = payload.claims;
944
951
  }
945
952
  let user = state.getUserByLocalId(localId);
946
- const isNewUser = state.usageMode === state_1.UsageMode.PASSTHROUGH ? false : !user;
953
+ const isNewUser = !user;
954
+ const timestamp = new Date();
947
955
  const updates = {
948
956
  customAuth: true,
949
- lastLoginAt: Date.now().toString(),
957
+ lastLoginAt: timestamp.getTime().toString(),
950
958
  tenantId: state instanceof state_1.TenantProjectState ? state.tenantId : undefined,
951
959
  };
952
960
  if (user) {
@@ -954,6 +962,7 @@ function signInWithCustomToken(state, reqBody) {
954
962
  user = state.updateUserByLocalId(localId, updates);
955
963
  }
956
964
  else {
965
+ updates.createdAt = timestamp.getTime().toString();
957
966
  user = state.createUserWithLocalId(localId, updates);
958
967
  if (!user) {
959
968
  throw new Error(`Internal assertion error: trying to create duplicate localId: ${localId}`);
@@ -961,11 +970,9 @@ function signInWithCustomToken(state, reqBody) {
961
970
  }
962
971
  return Object.assign({ kind: "identitytoolkit#VerifyCustomTokenResponse", isNewUser }, issueTokens(state, user, state_1.PROVIDER_CUSTOM, { extraClaims }));
963
972
  }
964
- function signInWithEmailLink(state, reqBody) {
965
- var _a;
973
+ async function signInWithEmailLink(state, reqBody) {
966
974
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
967
975
  (0, errors_1.assert)(state.enableEmailLinkSignin, "OPERATION_NOT_ALLOWED");
968
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
969
976
  const userFromIdToken = reqBody.idToken ? parseIdToken(state, reqBody.idToken).user : undefined;
970
977
  (0, errors_1.assert)(reqBody.email, "MISSING_EMAIL");
971
978
  const email = (0, utils_1.canonicalizeEmailAddress)(reqBody.email);
@@ -974,7 +981,11 @@ function signInWithEmailLink(state, reqBody) {
974
981
  (0, errors_1.assert)(oob && oob.requestType === "EMAIL_SIGNIN", "INVALID_OOB_CODE");
975
982
  (0, errors_1.assert)(email === oob.email, "INVALID_EMAIL : The email provided does not match the sign-in email address.");
976
983
  state.deleteOobCode(reqBody.oobCode);
977
- const updates = {
984
+ const userFromEmail = state.getUserByEmail(email);
985
+ let user = userFromIdToken || userFromEmail;
986
+ const isNewUser = !user;
987
+ const timestamp = new Date();
988
+ let updates = {
978
989
  email,
979
990
  emailVerified: true,
980
991
  emailLinkSignin: true,
@@ -982,19 +993,31 @@ function signInWithEmailLink(state, reqBody) {
982
993
  if (state instanceof state_1.TenantProjectState) {
983
994
  updates.tenantId = state.tenantId;
984
995
  }
985
- let user = state.getUserByEmail(email);
986
- const isNewUser = !user && !userFromIdToken;
996
+ let extraClaims;
987
997
  if (!user) {
988
- if (userFromIdToken) {
989
- user = state.updateUserByLocalId(userFromIdToken.localId, updates);
990
- }
991
- else {
992
- user = state.createUser(updates);
998
+ updates.createdAt = timestamp.getTime().toString();
999
+ const localId = state.generateLocalId();
1000
+ const userBeforeCreate = Object.assign({ localId }, updates);
1001
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "emailLink" });
1002
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1003
+ user = state.createUserWithLocalId(localId, updates);
1004
+ if (!user.disabled && !isMfaEnabled(state, user)) {
1005
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "emailLink" });
1006
+ updates = blockingResponse.updates;
1007
+ extraClaims = blockingResponse.extraClaims;
1008
+ user = state.updateUserByLocalId(user.localId, updates);
993
1009
  }
994
1010
  }
995
1011
  else {
996
1012
  (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
997
- (0, errors_1.assert)(!userFromIdToken || userFromIdToken.localId === user.localId, "EMAIL_EXISTS");
1013
+ if (userFromIdToken && userFromEmail) {
1014
+ (0, errors_1.assert)(userFromIdToken.localId === userFromEmail.localId, "EMAIL_EXISTS");
1015
+ }
1016
+ if (!user.disabled && !isMfaEnabled(state, user)) {
1017
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, Object.assign(Object.assign({}, user), updates), { signInMethod: "emailLink" });
1018
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1019
+ extraClaims = blockingResponse.extraClaims;
1020
+ }
998
1021
  user = state.updateUserByLocalId(user.localId, updates);
999
1022
  }
1000
1023
  const response = {
@@ -1003,19 +1026,18 @@ function signInWithEmailLink(state, reqBody) {
1003
1026
  localId: user.localId,
1004
1027
  isNewUser,
1005
1028
  };
1006
- if ((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
1007
- ((_a = user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length)) {
1029
+ (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
1030
+ if (isMfaEnabled(state, user)) {
1008
1031
  return Object.assign(Object.assign({}, response), mfaPending(state, user, state_1.PROVIDER_PASSWORD));
1009
1032
  }
1010
1033
  else {
1011
1034
  user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
1012
- return Object.assign(Object.assign({}, response), issueTokens(state, user, state_1.PROVIDER_PASSWORD));
1035
+ return Object.assign(Object.assign({}, response), issueTokens(state, user, state_1.PROVIDER_PASSWORD, { extraClaims }));
1013
1036
  }
1014
1037
  }
1015
- function signInWithIdp(state, reqBody) {
1016
- var _a, _b, _c;
1038
+ async function signInWithIdp(state, reqBody) {
1039
+ var _a, _b;
1017
1040
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
1018
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
1019
1041
  if (reqBody.returnRefreshToken) {
1020
1042
  throw new errors_1.NotImplementedError("returnRefreshToken is not implemented yet.");
1021
1043
  }
@@ -1095,15 +1117,55 @@ function signInWithIdp(state, reqBody) {
1095
1117
  screenName: response.screenName,
1096
1118
  };
1097
1119
  let user;
1120
+ let extraClaims;
1121
+ const oauthTokens = {
1122
+ oauthIdToken: response.oauthIdToken,
1123
+ oauthAccessToken: response.oauthAccessToken,
1124
+ oauthRefreshToken: response.oauthRefreshToken,
1125
+ oauthTokenSecret: response.oauthTokenSecret,
1126
+ oauthExpiresIn: coercePrimitiveToString(response.oauthExpireIn),
1127
+ };
1098
1128
  if (response.isNewUser) {
1099
- user = state.createUser(Object.assign(Object.assign({}, accountUpdates.fields), { lastLoginAt: Date.now().toString(), providerUserInfo: [providerUserInfo], tenantId: state instanceof state_1.TenantProjectState ? state.tenantId : undefined }));
1129
+ let updates = Object.assign(Object.assign({}, accountUpdates.fields), { lastLoginAt: Date.now().toString(), providerUserInfo: [providerUserInfo], tenantId: state instanceof state_1.TenantProjectState ? state.tenantId : undefined });
1130
+ const localId = state.generateLocalId();
1131
+ const userBeforeCreate = Object.assign({ localId }, updates);
1132
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, {
1133
+ signInMethod: response.providerId,
1134
+ rawUserInfo: response.rawUserInfo,
1135
+ signInAttributes: JSON.stringify(signInAttributes),
1136
+ }, oauthTokens);
1137
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1138
+ user = state.createUserWithLocalId(localId, updates);
1100
1139
  response.localId = user.localId;
1140
+ if (!user.disabled && !isMfaEnabled(state, user)) {
1141
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, {
1142
+ signInMethod: response.providerId,
1143
+ rawUserInfo: response.rawUserInfo,
1144
+ signInAttributes: JSON.stringify(signInAttributes),
1145
+ }, oauthTokens);
1146
+ updates = blockingResponse.updates;
1147
+ extraClaims = blockingResponse.extraClaims;
1148
+ user = state.updateUserByLocalId(user.localId, updates);
1149
+ }
1101
1150
  }
1102
1151
  else {
1103
1152
  if (!response.localId) {
1104
1153
  throw new Error("Internal assertion error: localId not set for exising user.");
1105
1154
  }
1106
- user = state.updateUserByLocalId(response.localId, Object.assign({}, accountUpdates.fields), {
1155
+ const maybeUser = state.getUserByLocalId(response.localId);
1156
+ (0, errors_1.assert)(maybeUser, "USER_NOT_FOUND");
1157
+ user = maybeUser;
1158
+ let updates = Object.assign({}, accountUpdates.fields);
1159
+ if (!user.disabled && !isMfaEnabled(state, user)) {
1160
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, Object.assign(Object.assign({}, user), updates), {
1161
+ signInMethod: response.providerId,
1162
+ rawUserInfo: response.rawUserInfo,
1163
+ signInAttributes: JSON.stringify(signInAttributes),
1164
+ }, oauthTokens);
1165
+ extraClaims = blockingResponse.extraClaims;
1166
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1167
+ }
1168
+ user = state.updateUserByLocalId(response.localId, updates, {
1107
1169
  upsertProviders: [providerUserInfo],
1108
1170
  });
1109
1171
  }
@@ -1113,20 +1175,18 @@ function signInWithIdp(state, reqBody) {
1113
1175
  if (state instanceof state_1.TenantProjectState) {
1114
1176
  response.tenantId = state.tenantId;
1115
1177
  }
1116
- if ((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
1117
- ((_c = user.mfaInfo) === null || _c === void 0 ? void 0 : _c.length)) {
1178
+ if (isMfaEnabled(state, user)) {
1118
1179
  return Object.assign(Object.assign({}, response), mfaPending(state, user, providerId));
1119
1180
  }
1120
1181
  else {
1121
1182
  user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
1122
- return Object.assign(Object.assign({}, response), issueTokens(state, user, providerId, { signInAttributes }));
1183
+ (0, errors_1.assert)(!(user === null || user === void 0 ? void 0 : user.disabled), "USER_DISABLED");
1184
+ return Object.assign(Object.assign({}, response), issueTokens(state, user, providerId, { signInAttributes, extraClaims }));
1123
1185
  }
1124
1186
  }
1125
- function signInWithPassword(state, reqBody) {
1126
- var _a;
1187
+ async function signInWithPassword(state, reqBody) {
1127
1188
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
1128
1189
  (0, errors_1.assert)(state.allowPasswordSignup, "PASSWORD_LOGIN_DISABLED");
1129
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
1130
1190
  (0, errors_1.assert)(reqBody.email, "MISSING_EMAIL");
1131
1191
  (0, errors_1.assert)(reqBody.password, "MISSING_PASSWORD");
1132
1192
  if (reqBody.captchaResponse || reqBody.captchaChallenge) {
@@ -1147,20 +1207,20 @@ function signInWithPassword(state, reqBody) {
1147
1207
  localId: user.localId,
1148
1208
  email,
1149
1209
  };
1150
- if ((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
1151
- ((_a = user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length)) {
1210
+ if (isMfaEnabled(state, user)) {
1152
1211
  return Object.assign(Object.assign({}, response), mfaPending(state, user, state_1.PROVIDER_PASSWORD));
1153
1212
  }
1154
1213
  else {
1155
- user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
1156
- return Object.assign(Object.assign({}, response), issueTokens(state, user, state_1.PROVIDER_PASSWORD));
1214
+ const { updates, extraClaims } = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "password" });
1215
+ user = state.updateUserByLocalId(user.localId, Object.assign(Object.assign({}, updates), { lastLoginAt: Date.now().toString() }));
1216
+ (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
1217
+ return Object.assign(Object.assign({}, response), issueTokens(state, user, state_1.PROVIDER_PASSWORD, { extraClaims }));
1157
1218
  }
1158
1219
  }
1159
- function signInWithPhoneNumber(state, reqBody) {
1220
+ async function signInWithPhoneNumber(state, reqBody) {
1160
1221
  var _a;
1161
1222
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
1162
1223
  (0, errors_1.assert)(state instanceof state_1.AgentProjectState, "UNSUPPORTED_TENANT_OPERATION");
1163
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
1164
1224
  let phoneNumber;
1165
1225
  if (reqBody.temporaryProof) {
1166
1226
  (0, errors_1.assert)(reqBody.phoneNumber, "MISSING_PHONE_NUMBER");
@@ -1173,39 +1233,54 @@ function signInWithPhoneNumber(state, reqBody) {
1173
1233
  (0, errors_1.assert)(reqBody.code, "MISSING_CODE");
1174
1234
  phoneNumber = verifyPhoneNumber(state, reqBody.sessionInfo, reqBody.code);
1175
1235
  }
1176
- let user = state.getUserByPhoneNumber(phoneNumber);
1177
- let isNewUser = false;
1178
- const updates = {
1236
+ const userFromPhoneNumber = state.getUserByPhoneNumber(phoneNumber);
1237
+ const userFromIdToken = reqBody.idToken ? parseIdToken(state, reqBody.idToken).user : undefined;
1238
+ if (userFromPhoneNumber && userFromIdToken) {
1239
+ if (userFromPhoneNumber.localId !== userFromIdToken.localId) {
1240
+ (0, errors_1.assert)(!reqBody.temporaryProof, "PHONE_NUMBER_EXISTS");
1241
+ return Object.assign({}, state.createTemporaryProof(phoneNumber));
1242
+ }
1243
+ }
1244
+ let user = userFromIdToken || userFromPhoneNumber;
1245
+ const isNewUser = !user;
1246
+ const timestamp = new Date();
1247
+ let updates = {
1179
1248
  phoneNumber,
1180
- lastLoginAt: Date.now().toString(),
1249
+ lastLoginAt: timestamp.getTime().toString(),
1181
1250
  };
1182
- const userFromIdToken = reqBody.idToken ? parseIdToken(state, reqBody.idToken).user : undefined;
1251
+ let extraClaims;
1183
1252
  if (!user) {
1184
- if (userFromIdToken) {
1185
- (0, errors_1.assert)(!((_a = userFromIdToken.mfaInfo) === null || _a === void 0 ? void 0 : _a.length), "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
1186
- user = state.updateUserByLocalId(userFromIdToken.localId, updates);
1187
- }
1188
- else {
1189
- isNewUser = true;
1190
- user = state.createUser(updates);
1253
+ updates.createdAt = timestamp.getTime().toString();
1254
+ const localId = state.generateLocalId();
1255
+ const userBeforeCreate = Object.assign({ localId }, updates);
1256
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "phone" });
1257
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1258
+ user = state.createUserWithLocalId(localId, updates);
1259
+ if (!user.disabled) {
1260
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "phone" });
1261
+ updates = blockingResponse.updates;
1262
+ extraClaims = blockingResponse.extraClaims;
1263
+ user = state.updateUserByLocalId(user.localId, updates);
1191
1264
  }
1192
1265
  }
1193
1266
  else {
1194
1267
  (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
1195
- if (userFromIdToken && userFromIdToken.localId !== user.localId) {
1196
- if (!reqBody.temporaryProof) {
1197
- return Object.assign({}, state.createTemporaryProof(phoneNumber));
1198
- }
1199
- throw new errors_1.BadRequestError("PHONE_NUMBER_EXISTS");
1268
+ (0, errors_1.assert)(!((_a = user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length), "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
1269
+ if (!user.disabled) {
1270
+ const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, Object.assign(Object.assign({}, user), updates), { signInMethod: "phone" });
1271
+ updates = Object.assign(Object.assign({}, updates), blockingResponse.updates);
1272
+ extraClaims = blockingResponse.extraClaims;
1200
1273
  }
1201
1274
  user = state.updateUserByLocalId(user.localId, updates);
1202
1275
  }
1203
- const tokens = issueTokens(state, user, state_1.PROVIDER_PHONE);
1276
+ (0, errors_1.assert)(!(user === null || user === void 0 ? void 0 : user.disabled), "USER_DISABLED");
1277
+ const tokens = issueTokens(state, user, state_1.PROVIDER_PHONE, {
1278
+ extraClaims,
1279
+ });
1204
1280
  return Object.assign({ isNewUser,
1205
1281
  phoneNumber, localId: user.localId }, tokens);
1206
1282
  }
1207
1283
  function grantToken(state, reqBody) {
1208
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
1209
1284
  (0, errors_1.assert)(reqBody.grantType, "MISSING_GRANT_TYPE");
1210
1285
  (0, errors_1.assert)(reqBody.grantType === "refresh_token", "INVALID_GRANT_TYPE");
1211
1286
  (0, errors_1.assert)(reqBody.refreshToken, "MISSING_REFRESH_TOKEN");
@@ -1234,7 +1309,6 @@ function getEmulatorProjectConfig(state) {
1234
1309
  signIn: {
1235
1310
  allowDuplicateEmails: !state.oneAccountPerEmail,
1236
1311
  },
1237
- usageMode: state.usageMode,
1238
1312
  };
1239
1313
  }
1240
1314
  function updateEmulatorProjectConfig(state, reqBody, ctx) {
@@ -1243,9 +1317,6 @@ function updateEmulatorProjectConfig(state, reqBody, ctx) {
1243
1317
  if (((_a = reqBody.signIn) === null || _a === void 0 ? void 0 : _a.allowDuplicateEmails) != null) {
1244
1318
  updateMask.push("signIn.allowDuplicateEmails");
1245
1319
  }
1246
- if (reqBody.usageMode) {
1247
- updateMask.push("usageMode");
1248
- }
1249
1320
  ctx.params.query.updateMask = updateMask.join();
1250
1321
  updateConfig(state, reqBody, ctx);
1251
1322
  return getEmulatorProjectConfig(state);
@@ -1353,7 +1424,7 @@ function mfaSignInStart(state, reqBody) {
1353
1424
  },
1354
1425
  };
1355
1426
  }
1356
- function mfaSignInFinalize(state, reqBody) {
1427
+ async function mfaSignInFinalize(state, reqBody) {
1357
1428
  var _a, _b;
1358
1429
  (0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
1359
1430
  (0, errors_1.assert)((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
@@ -1369,10 +1440,12 @@ function mfaSignInFinalize(state, reqBody) {
1369
1440
  const phoneNumber = verifyPhoneNumber(state, sessionInfo, code);
1370
1441
  let { user, signInProvider } = parsePendingCredential(state, reqBody.mfaPendingCredential);
1371
1442
  const enrollment = (_b = user.mfaInfo) === null || _b === void 0 ? void 0 : _b.find((enrollment) => enrollment.unobfuscatedPhoneInfo === phoneNumber);
1443
+ const { updates, extraClaims } = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: signInProvider, signInSecondFactor: "phone" });
1444
+ user = state.updateUserByLocalId(user.localId, Object.assign(Object.assign({}, updates), { lastLoginAt: Date.now().toString() }));
1372
1445
  (0, errors_1.assert)(enrollment && enrollment.mfaEnrollmentId, "MFA_ENROLLMENT_NOT_FOUND");
1373
- user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
1374
1446
  (0, errors_1.assert)(!user.disabled, "USER_DISABLED");
1375
1447
  const { idToken, refreshToken } = issueTokens(state, user, signInProvider, {
1448
+ extraClaims,
1376
1449
  secondFactor: { identifier: enrollment.mfaEnrollmentId, provider: state_1.PROVIDER_PHONE },
1377
1450
  });
1378
1451
  return {
@@ -1380,7 +1453,7 @@ function mfaSignInFinalize(state, reqBody) {
1380
1453
  refreshToken,
1381
1454
  };
1382
1455
  }
1383
- function getConfig(state, reqBody, ctx) {
1456
+ function getConfig(state) {
1384
1457
  (0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Can only get top-level configurations on agent projects.))");
1385
1458
  return state.config;
1386
1459
  }
@@ -1414,7 +1487,6 @@ function hashPassword(password, salt) {
1414
1487
  }
1415
1488
  function issueTokens(state, user, signInProvider, { extraClaims, secondFactor, signInAttributes, } = {}) {
1416
1489
  user = state.updateUserByLocalId(user.localId, { lastRefreshAt: new Date().toISOString() });
1417
- const usageMode = state.usageMode === state_1.UsageMode.PASSTHROUGH ? "passthrough" : undefined;
1418
1490
  const tenantId = state instanceof state_1.TenantProjectState ? state.tenantId : undefined;
1419
1491
  const expiresInSeconds = 60 * 60;
1420
1492
  const idToken = generateJwt(user, {
@@ -1423,16 +1495,13 @@ function issueTokens(state, user, signInProvider, { extraClaims, secondFactor, s
1423
1495
  expiresInSeconds,
1424
1496
  extraClaims,
1425
1497
  secondFactor,
1426
- usageMode,
1427
1498
  tenantId,
1428
1499
  signInAttributes,
1429
1500
  });
1430
- const refreshToken = state.usageMode === state_1.UsageMode.DEFAULT
1431
- ? state.createRefreshTokenFor(user, signInProvider, {
1432
- extraClaims,
1433
- secondFactor,
1434
- })
1435
- : undefined;
1501
+ const refreshToken = state.createRefreshTokenFor(user, signInProvider, {
1502
+ extraClaims,
1503
+ secondFactor,
1504
+ });
1436
1505
  return {
1437
1506
  idToken,
1438
1507
  refreshToken,
@@ -1440,7 +1509,6 @@ function issueTokens(state, user, signInProvider, { extraClaims, secondFactor, s
1440
1509
  };
1441
1510
  }
1442
1511
  function parseIdToken(state, idToken) {
1443
- (0, errors_1.assert)(state.usageMode !== state_1.UsageMode.PASSTHROUGH, "UNSUPPORTED_PASSTHROUGH_OPERATION");
1444
1512
  const decoded = (0, jsonwebtoken_1.decode)(idToken, { complete: true });
1445
1513
  (0, errors_1.assert)(decoded, "INVALID_ID_TOKEN");
1446
1514
  if (decoded.header.alg !== "none") {
@@ -1457,7 +1525,7 @@ function parseIdToken(state, idToken) {
1457
1525
  const signInProvider = decoded.payload.firebase.sign_in_provider;
1458
1526
  return { user, signInProvider, payload: decoded.payload };
1459
1527
  }
1460
- function generateJwt(user, { projectId, signInProvider, expiresInSeconds, extraClaims = {}, secondFactor, usageMode, tenantId, signInAttributes, }) {
1528
+ function generateJwt(user, { projectId, signInProvider, expiresInSeconds, extraClaims = {}, secondFactor, tenantId, signInAttributes, }) {
1461
1529
  const identities = {};
1462
1530
  if (user.email) {
1463
1531
  identities["email"] = [user.email];
@@ -1479,7 +1547,6 @@ function generateJwt(user, { projectId, signInProvider, expiresInSeconds, extraC
1479
1547
  sign_in_provider: signInProvider,
1480
1548
  second_factor_identifier: secondFactor === null || secondFactor === void 0 ? void 0 : secondFactor.identifier,
1481
1549
  sign_in_second_factor: secondFactor === null || secondFactor === void 0 ? void 0 : secondFactor.provider,
1482
- usage_mode: usageMode,
1483
1550
  tenant: tenantId,
1484
1551
  sign_in_attributes: signInAttributes,
1485
1552
  } });
@@ -1867,12 +1934,12 @@ function listTenants(state, reqBody, ctx) {
1867
1934
  tenants,
1868
1935
  };
1869
1936
  }
1870
- function deleteTenant(state, reqBody, ctx) {
1937
+ function deleteTenant(state) {
1871
1938
  (0, errors_1.assert)(state instanceof state_1.TenantProjectState, "((Can only delete tenant on tenant projects.))");
1872
1939
  state.delete();
1873
1940
  return {};
1874
1941
  }
1875
- function getTenant(state, reqBody, ctx) {
1942
+ function getTenant(state) {
1876
1943
  (0, errors_1.assert)(state instanceof state_1.TenantProjectState, "((Can only get tenant on tenant projects.))");
1877
1944
  return state.tenantConfig;
1878
1945
  }
@@ -1880,3 +1947,185 @@ function updateTenant(state, reqBody, ctx) {
1880
1947
  (0, errors_1.assert)(state instanceof state_1.TenantProjectState, "((Can only update tenant on tenant projects.))");
1881
1948
  return state.updateTenant(reqBody, ctx.params.query.updateMask);
1882
1949
  }
1950
+ function isMfaEnabled(state, user) {
1951
+ var _a;
1952
+ return ((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
1953
+ ((_a = user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length));
1954
+ }
1955
+ async function fetchBlockingFunction(state, event, user, options = {}, oauthTokens = {}, timeoutMs = 60000) {
1956
+ const url = state.getBlockingFunctionUri(event);
1957
+ if (!url) {
1958
+ return { updates: {} };
1959
+ }
1960
+ const jwt = generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options, oauthTokens);
1961
+ const reqBody = {
1962
+ data: {
1963
+ jwt,
1964
+ },
1965
+ };
1966
+ const controller = new abort_controller_1.default();
1967
+ const timeout = setTimeout(() => {
1968
+ controller.abort();
1969
+ }, timeoutMs);
1970
+ let response;
1971
+ try {
1972
+ const res = await (0, node_fetch_1.default)(url, {
1973
+ method: "POST",
1974
+ headers: { "Content-Type": "application/json" },
1975
+ body: JSON.stringify(reqBody),
1976
+ signal: controller.signal,
1977
+ });
1978
+ const text = await res.text();
1979
+ (0, errors_1.assert)(res.ok, `BLOCKING_FUNCTION_ERROR_RESPONSE: ((HTTP request to ${url} returned HTTP error${res.status}: ${text}))`);
1980
+ response = JSON.parse(text);
1981
+ }
1982
+ catch (thrown) {
1983
+ const err = thrown instanceof Error ? thrown : new Error(thrown);
1984
+ const isAbortError = err.name.includes("AbortError");
1985
+ if (isAbortError) {
1986
+ throw new errors_1.InternalError(`BLOCKING_FUNCTION_ERROR_RESPONSE: ((Deadline exceeded making request to ${url}.))`, err.message);
1987
+ }
1988
+ throw new errors_1.InternalError(`BLOCKING_FUNCTION_ERROR_RESPONSE: ((Failed to make request to ${url}.))`, err.message);
1989
+ }
1990
+ finally {
1991
+ clearTimeout(timeout);
1992
+ }
1993
+ return processBlockingFunctionResponse(event, response);
1994
+ }
1995
+ function processBlockingFunctionResponse(event, response) {
1996
+ let extraClaims;
1997
+ const updates = {};
1998
+ if (response.userRecord) {
1999
+ const userRecord = response.userRecord;
2000
+ (0, errors_1.assert)(userRecord.updateMask, "BLOCKING_FUNCTION_ERROR_RESPONSE: ((Response UserRecord is missing updateMask.))");
2001
+ const mask = userRecord.updateMask;
2002
+ const fields = mask.split(",");
2003
+ for (const field of fields) {
2004
+ switch (field) {
2005
+ case "displayName":
2006
+ case "photoUrl":
2007
+ updates[field] = coercePrimitiveToString(userRecord[field]);
2008
+ break;
2009
+ case "disabled":
2010
+ case "emailVerified":
2011
+ updates[field] = !!userRecord[field];
2012
+ break;
2013
+ case "customClaims":
2014
+ validateSerializedCustomClaims(userRecord.customClaims);
2015
+ updates.customAttributes = userRecord.customClaims;
2016
+ break;
2017
+ case "sessionClaims":
2018
+ if (event !== state_1.BlockingFunctionEvents.BEFORE_SIGN_IN) {
2019
+ break;
2020
+ }
2021
+ try {
2022
+ extraClaims = JSON.parse(userRecord.sessionClaims);
2023
+ }
2024
+ catch (_a) {
2025
+ throw new errors_1.BadRequestError("BLOCKING_FUNCTION_ERROR_RESPONSE: ((Response has malformed session claims.))");
2026
+ }
2027
+ break;
2028
+ default:
2029
+ break;
2030
+ }
2031
+ }
2032
+ }
2033
+ return { updates, extraClaims };
2034
+ }
2035
+ function generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options, oauthTokens) {
2036
+ const issuedAt = (0, utils_1.toUnixTimestamp)(new Date());
2037
+ const jwt = {
2038
+ iss: `https://securetoken.google.com/${state.projectId}`,
2039
+ aud: url,
2040
+ iat: issuedAt,
2041
+ exp: issuedAt + timeoutMs / 100,
2042
+ event_id: (0, utils_1.randomBase64UrlStr)(16),
2043
+ event_type: event,
2044
+ user_agent: "NotYetSupportedInFirebaseAuthEmulator",
2045
+ ip_address: "127.0.0.1",
2046
+ locale: "en",
2047
+ user_record: {
2048
+ uid: user.localId,
2049
+ email: user.email,
2050
+ email_verified: user.emailVerified,
2051
+ display_name: user.displayName,
2052
+ photo_url: user.photoUrl,
2053
+ disabled: user.disabled,
2054
+ phone_number: user.phoneNumber,
2055
+ custom_claims: user.customAttributes,
2056
+ },
2057
+ sub: user.localId,
2058
+ sign_in_method: options.signInMethod,
2059
+ sign_in_second_factor: options.signInSecondFactor,
2060
+ sign_in_attributes: options.signInAttributes,
2061
+ raw_user_info: options.rawUserInfo,
2062
+ };
2063
+ if (state instanceof state_1.TenantProjectState) {
2064
+ jwt.tenant_id = state.tenantId;
2065
+ jwt.user_record.tenant_id = state.tenantId;
2066
+ }
2067
+ const provider_data = [];
2068
+ if (user.providerUserInfo) {
2069
+ for (const providerUserInfo of user.providerUserInfo) {
2070
+ const provider = {
2071
+ provider_id: providerUserInfo.providerId,
2072
+ display_name: providerUserInfo.displayName,
2073
+ photo_url: providerUserInfo.photoUrl,
2074
+ email: providerUserInfo.email,
2075
+ uid: providerUserInfo.rawId,
2076
+ phone_number: providerUserInfo.phoneNumber,
2077
+ };
2078
+ provider_data.push(provider);
2079
+ }
2080
+ }
2081
+ jwt.user_record.provider_data = provider_data;
2082
+ if (user.mfaInfo) {
2083
+ const enrolled_factors = [];
2084
+ for (const mfaEnrollment of user.mfaInfo) {
2085
+ if (!mfaEnrollment.mfaEnrollmentId) {
2086
+ continue;
2087
+ }
2088
+ const enrolledFactor = {
2089
+ uid: mfaEnrollment.mfaEnrollmentId,
2090
+ display_name: mfaEnrollment.displayName,
2091
+ enrollment_time: mfaEnrollment.enrolledAt,
2092
+ phone_number: mfaEnrollment.phoneInfo,
2093
+ factor_id: state_1.PROVIDER_PHONE,
2094
+ };
2095
+ enrolled_factors.push(enrolledFactor);
2096
+ }
2097
+ jwt.user_record.multi_factor = {
2098
+ enrolled_factors,
2099
+ };
2100
+ }
2101
+ if (user.lastLoginAt || user.createdAt) {
2102
+ jwt.user_record.metadata = {
2103
+ last_sign_in_time: user.lastLoginAt,
2104
+ creation_time: user.createdAt,
2105
+ };
2106
+ }
2107
+ if (state.shouldForwardCredentialToBlockingFunction("accessToken")) {
2108
+ jwt.oauth_access_token = oauthTokens.oauthAccessToken;
2109
+ jwt.oauth_token_secret = oauthTokens.oauthTokenSecret;
2110
+ jwt.oauth_expires_in = oauthTokens.oauthExpiresIn;
2111
+ }
2112
+ if (state.shouldForwardCredentialToBlockingFunction("idToken")) {
2113
+ jwt.oauth_id_token = oauthTokens.oauthIdToken;
2114
+ }
2115
+ if (state.shouldForwardCredentialToBlockingFunction("refreshToken")) {
2116
+ jwt.oauth_refresh_token = oauthTokens.oauthRefreshToken;
2117
+ }
2118
+ const jwtStr = (0, jsonwebtoken_1.sign)(jwt, "", {
2119
+ algorithm: "none",
2120
+ });
2121
+ return jwtStr;
2122
+ }
2123
+ function parseBlockingFunctionJwt(jwt) {
2124
+ const decoded = (0, jsonwebtoken_1.decode)(jwt, { json: true });
2125
+ (0, errors_1.assert)(decoded, "((Invalid blocking function jwt.))");
2126
+ (0, errors_1.assert)(decoded.iss, "((Invalid blocking function jwt, missing `iss` claim.))");
2127
+ (0, errors_1.assert)(decoded.aud, "((Invalid blocking function jwt, missing `aud` claim.))");
2128
+ (0, errors_1.assert)(decoded.user_record, "((Invalid blocking function jwt, missing `user_record` claim.))");
2129
+ return decoded;
2130
+ }
2131
+ exports.parseBlockingFunctionJwt = parseBlockingFunctionJwt;