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.
- package/lib/accountExporter.js +11 -4
- package/lib/accountImporter.js +93 -95
- package/lib/api.js +77 -218
- package/lib/apiv2.js +5 -4
- package/lib/appdistribution/client.js +7 -9
- package/lib/auth.js +72 -52
- package/lib/bin/firebase.js +42 -47
- package/lib/checkValidTargetFilters.js +36 -25
- package/lib/commands/appdistribution-distribute.js +2 -1
- package/lib/commands/appdistribution-testers-add.js +2 -1
- package/lib/commands/appdistribution-testers-remove.js +2 -1
- package/lib/commands/apps-android-sha-create.js +2 -1
- package/lib/commands/apps-android-sha-delete.js +2 -1
- package/lib/commands/apps-android-sha-list.js +2 -1
- package/lib/commands/apps-create.js +2 -1
- package/lib/commands/apps-list.js +2 -1
- package/lib/commands/apps-sdkconfig.js +2 -1
- package/lib/commands/auth-export.js +2 -1
- package/lib/commands/auth-import.js +7 -10
- package/lib/commands/crashlytics-symbols-upload.js +2 -1
- package/lib/commands/database-get.js +4 -3
- package/lib/commands/database-instances-create.js +2 -1
- package/lib/commands/database-instances-list.js +3 -3
- package/lib/commands/database-profile.js +4 -4
- package/lib/commands/database-push.js +4 -4
- package/lib/commands/database-remove.js +3 -3
- package/lib/commands/database-rules-canary.js +2 -1
- package/lib/commands/database-rules-get.js +2 -1
- package/lib/commands/database-rules-list.js +2 -1
- package/lib/commands/database-rules-release.js +2 -1
- package/lib/commands/database-rules-stage.js +2 -1
- package/lib/commands/database-set.js +3 -3
- package/lib/commands/database-settings-get.js +2 -1
- package/lib/commands/database-settings-set.js +2 -1
- package/lib/commands/database-update.js +2 -1
- package/lib/commands/deploy.js +26 -25
- package/lib/commands/emulators-exec.js +2 -1
- package/lib/commands/emulators-export.js +2 -1
- package/lib/commands/emulators-start.js +2 -1
- package/lib/commands/experimental-functions-shell.js +10 -8
- package/lib/commands/ext-configure.js +2 -1
- package/lib/commands/ext-dev-deprecate.js +2 -1
- package/lib/commands/ext-dev-emulators-exec.js +3 -2
- package/lib/commands/ext-dev-emulators-start.js +3 -2
- package/lib/commands/ext-dev-extension-delete.js +2 -1
- package/lib/commands/ext-dev-init.js +2 -1
- package/lib/commands/ext-dev-list.js +8 -8
- package/lib/commands/ext-dev-publish.js +2 -1
- package/lib/commands/ext-dev-register.js +2 -1
- package/lib/commands/ext-dev-undeprecate.js +2 -1
- package/lib/commands/ext-dev-unpublish.js +2 -1
- package/lib/commands/ext-dev-usage.js +2 -1
- package/lib/commands/ext-export.js +2 -1
- package/lib/commands/ext-info.js +14 -14
- package/lib/commands/ext-install.js +2 -1
- package/lib/commands/ext-list.js +2 -1
- package/lib/commands/ext-sources-create.js +2 -1
- package/lib/commands/ext-uninstall.js +2 -1
- package/lib/commands/ext-update.js +2 -1
- package/lib/commands/ext.js +4 -4
- package/lib/commands/firestore-delete.js +2 -1
- package/lib/commands/firestore-indexes-list.js +2 -1
- package/lib/commands/functions-config-clone.js +4 -3
- package/lib/commands/functions-config-export.js +2 -1
- package/lib/commands/functions-config-get.js +2 -1
- package/lib/commands/functions-config-set.js +2 -1
- package/lib/commands/functions-config-unset.js +2 -1
- package/lib/commands/functions-delete.js +3 -8
- package/lib/commands/functions-deletegcfartifacts.js +2 -1
- package/lib/commands/functions-list.js +2 -1
- package/lib/commands/functions-log.js +2 -1
- package/lib/commands/functions-secrets-access.js +2 -1
- package/lib/commands/functions-secrets-destroy.js +2 -1
- package/lib/commands/functions-secrets-get.js +2 -1
- package/lib/commands/functions-secrets-prune.js +2 -1
- package/lib/commands/functions-secrets-set.js +2 -1
- package/lib/commands/functions-shell.js +12 -10
- package/lib/commands/help.js +2 -1
- package/lib/commands/hosting-channel-create.js +2 -1
- package/lib/commands/hosting-channel-delete.js +2 -1
- package/lib/commands/hosting-channel-deploy.js +2 -1
- package/lib/commands/hosting-channel-list.js +2 -1
- package/lib/commands/hosting-channel-open.js +2 -1
- package/lib/commands/hosting-clone.js +2 -1
- package/lib/commands/hosting-disable.js +2 -1
- package/lib/commands/hosting-sites-create.js +2 -1
- package/lib/commands/hosting-sites-delete.js +2 -1
- package/lib/commands/hosting-sites-get.js +2 -1
- package/lib/commands/hosting-sites-list.js +2 -1
- package/lib/commands/index.js +23 -13
- package/lib/commands/init.js +47 -43
- package/lib/commands/login-add.js +2 -1
- package/lib/commands/login-ci.js +2 -1
- package/lib/commands/login-list.js +2 -1
- package/lib/commands/login-use.js +2 -1
- package/lib/commands/login.js +2 -1
- package/lib/commands/logout.js +2 -1
- package/lib/commands/open.js +7 -7
- package/lib/commands/projects-addfirebase.js +2 -1
- package/lib/commands/projects-create.js +2 -1
- package/lib/commands/projects-list.js +2 -1
- package/lib/commands/remoteconfig-get.js +2 -1
- package/lib/commands/remoteconfig-rollback.js +2 -1
- package/lib/commands/remoteconfig-versions-list.js +2 -1
- package/lib/commands/serve.js +30 -30
- package/lib/commands/setup-emulators-database.js +2 -1
- package/lib/commands/setup-emulators-firestore.js +2 -1
- package/lib/commands/setup-emulators-pubsub.js +2 -1
- package/lib/commands/setup-emulators-storage.js +2 -1
- package/lib/commands/setup-emulators-ui.js +2 -1
- package/lib/commands/target-apply.js +2 -1
- package/lib/commands/target-clear.js +2 -1
- package/lib/commands/target-remove.js +2 -1
- package/lib/commands/target.js +2 -1
- package/lib/commands/use.js +54 -53
- package/lib/config.js +7 -6
- package/lib/deploy/database/deploy.js +3 -2
- package/lib/deploy/database/index.js +8 -5
- package/lib/deploy/database/prepare.js +22 -20
- package/lib/deploy/database/release.js +12 -9
- package/lib/deploy/extensions/secrets.js +3 -3
- package/lib/deploy/firestore/prepare.js +2 -2
- package/lib/deploy/functions/build.js +33 -20
- package/lib/deploy/functions/ensure.js +1 -11
- package/lib/deploy/functions/prepare.js +3 -13
- package/lib/deploy/functions/prepareFunctionsUpload.js +2 -3
- package/lib/deploy/functions/release/fabricator.js +0 -1
- package/lib/deploy/functions/release/index.js +1 -5
- package/lib/deploy/functions/runtimes/discovery/index.js +18 -3
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +188 -54
- package/lib/deploy/functions/runtimes/golang/index.js +2 -22
- package/lib/deploy/functions/runtimes/node/index.js +3 -7
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +16 -4
- package/lib/deploy/functions/services/database.js +14 -0
- package/lib/deploy/functions/services/index.js +14 -0
- package/lib/deploy/index.js +3 -3
- package/lib/deploy/lifecycleHooks.js +27 -27
- package/lib/deploy/remoteconfig/prepare.js +2 -2
- package/lib/deploy/storage/prepare.js +1 -1
- package/lib/emulator/auth/apiSpec.js +14 -46
- package/lib/emulator/auth/index.js +1 -1
- package/lib/emulator/auth/operations.js +342 -93
- package/lib/emulator/auth/server.js +2 -2
- package/lib/emulator/auth/state.js +34 -32
- package/lib/emulator/commandUtils.js +1 -1
- package/lib/emulator/constants.js +1 -1
- package/lib/emulator/controller.js +7 -6
- package/lib/emulator/databaseEmulator.js +4 -4
- package/lib/emulator/download.js +1 -1
- package/lib/emulator/downloadableEmulators.js +5 -5
- package/lib/emulator/events/types.js +2 -3
- package/lib/emulator/firestoreEmulator.js +2 -2
- package/lib/emulator/functionsEmulator.js +31 -45
- package/lib/emulator/functionsEmulatorRuntime.js +12 -16
- package/lib/emulator/functionsEmulatorShared.js +7 -5
- package/lib/emulator/functionsRuntimeWorker.js +0 -6
- package/lib/emulator/hostingEmulator.js +1 -1
- package/lib/emulator/hub.js +1 -1
- package/lib/emulator/loggingEmulator.js +1 -1
- package/lib/emulator/pubsubEmulator.js +1 -1
- package/lib/emulator/storage/crc.js +4 -4
- package/lib/emulator/storage/index.js +1 -1
- package/lib/emulator/types.js +1 -1
- package/lib/errorOut.js +2 -2
- package/lib/extensions/askUserForConsent.js +1 -2
- package/lib/extensions/askUserForParam.js +15 -18
- package/lib/extensions/emulator/optionsHelper.js +4 -4
- package/lib/extensions/extensionsApi.js +1 -22
- package/lib/extensions/extensionsHelper.js +6 -6
- package/lib/extensions/listExtensions.js +9 -10
- package/lib/extensions/manifest.js +2 -2
- package/lib/extensions/resolveSource.js +11 -7
- package/lib/extensions/secretsUtils.js +3 -3
- package/lib/extensions/types.js +24 -0
- package/lib/extensions/updateHelper.js +1 -1
- package/lib/extensions/utils.js +1 -2
- package/lib/extensions/warnings.js +3 -3
- package/lib/firestore/encodeFirestoreValue.js +11 -8
- package/lib/fsAsync.js +3 -3
- package/lib/functions/events/v2.js +7 -1
- package/lib/functionsConfig.js +17 -14
- package/lib/functionsConfigClone.js +46 -46
- package/lib/gcp/cloudfunctions.js +2 -15
- package/lib/gcp/cloudfunctionsv2.js +17 -2
- package/lib/gcp/iam.js +1 -1
- package/lib/gcp/index.js +10 -10
- package/lib/gcp/rules.js +1 -1
- package/lib/gcp/runtimeconfig.js +45 -47
- package/lib/hosting/proxy.js +1 -1
- package/lib/index.js +29 -28
- package/lib/init/features/database.js +10 -2
- package/lib/init/features/functions/index.js +1 -1
- package/lib/init/features/functions/javascript.js +23 -20
- package/lib/init/features/functions/npm-dependencies.js +17 -14
- package/lib/init/features/functions/typescript.js +27 -24
- package/lib/init/features/hosting/github.js +6 -5
- package/lib/init/features/hosting/index.js +2 -2
- package/lib/loadCJSON.js +9 -6
- package/lib/localFunction.js +4 -4
- package/lib/logError.js +15 -12
- package/lib/parseBoltRules.js +15 -14
- package/lib/previews.js +1 -1
- package/lib/profileReport.js +504 -512
- package/lib/profiler.js +4 -4
- package/lib/prompt.js +1 -2
- package/lib/rc.js +1 -1
- package/lib/requireAuth.js +0 -1
- package/lib/responseToError.js +8 -5
- package/lib/rulesDeploy.js +2 -2
- package/lib/scopes.js +9 -9
- package/lib/serve/index.js +4 -5
- package/lib/utils.js +30 -6
- package/npm-shrinkwrap.json +537 -193
- 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
|
|
111
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
178
|
-
|
|
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
|
|
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 =
|
|
953
|
+
const isNewUser = !user;
|
|
954
|
+
const timestamp = new Date();
|
|
947
955
|
const updates = {
|
|
948
956
|
customAuth: true,
|
|
949
|
-
lastLoginAt:
|
|
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
|
|
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
|
|
986
|
-
const isNewUser = !user && !userFromIdToken;
|
|
996
|
+
let extraClaims;
|
|
987
997
|
if (!user) {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1007
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1156
|
-
|
|
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
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
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:
|
|
1249
|
+
lastLoginAt: timestamp.getTime().toString(),
|
|
1181
1250
|
};
|
|
1182
|
-
|
|
1251
|
+
let extraClaims;
|
|
1183
1252
|
if (!user) {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
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,
|
|
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
|
|
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
|
|
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;
|