diff --git a/test/end-to-end/mfa.default_reqs.test.js b/test/end-to-end/mfa.default_reqs.test.js index 5b9c5fe70..d01c65450 100644 --- a/test/end-to-end/mfa.default_reqs.test.js +++ b/test/end-to-end/mfa.default_reqs.test.js @@ -32,7 +32,7 @@ import { getFactorChooserOptions, } from "../helpers"; import fetch from "isomorphic-fetch"; -import { CREATE_CODE_API, CREATE_TOTP_DEVICE_API, MFA_INFO_API } from "../constants"; +import { CREATE_CODE_API, CREATE_TOTP_DEVICE_API, MFA_INFO_API, TEST_APPLICATION_SERVER_BASE_URL } from "../constants"; import { TEST_CLIENT_BASE_URL, TEST_SERVER_BASE_URL } from "../constants"; import { getTestPhoneNumber } from "../exampleTestHelpers"; @@ -54,6 +54,7 @@ import { expectErrorThrown, waitForLoadingScreen, waitForBlockedScreen, + addToDefaultRequiredFactorsForUser, } from "./mfa.helpers"; /* @@ -150,25 +151,50 @@ describe("SuperTokens SignIn w/ MFA", function () { assert.deepStrictEqual(new Set(list), new Set(["otp-email", "otp-phone", "totp"])); }); - it("should require 2fa to sign in after setting up a factor", async () => { + it("should require 2fa to sign in after setting up a factor - totp", async () => { await tryEmailPasswordSignIn(page, email); await waitForDashboard(page); - await goToFactorChooser(page); - await chooseFactor(page, "otp-email"); - await completeOTP(page); - const secret = await setupTOTP(page); await logout(page); await tryEmailPasswordSignIn(page, email); - const list = await getFactorChooserOptions(page); - // TODO: validate this, maybe it should only be totp? - assert.deepStrictEqual(new Set(list), new Set(["otp-email", "totp"])); - await chooseFactor(page, "totp"); + await waitForDashboard(page); + await addToDefaultRequiredFactorsForUser(page, "totp"); + await logout(page); + + await tryEmailPasswordSignIn(page, email); await completeTOTP(page, secret); await waitForDashboard(page); }); + + it("should require 2fa to sign in after setting up a factor - otp-email", async () => { + await tryEmailPasswordSignIn(page, email); + await addToDefaultRequiredFactorsForUser(page, "otp-email"); + await logout(page); + + await tryEmailPasswordSignIn(page, email); + await completeOTP(page, "EMAIL"); + await waitForDashboard(page); + }); + + it("should require 2fa to sign in after setting up a factor - otp-phone", async () => { + await tryEmailPasswordSignIn(page, email); + + await waitForDashboard(page); + + await setupOTP(page, "PHONE", getTestPhoneNumber()); + await logout(page); + + await tryEmailPasswordSignIn(page, email); + await waitForDashboard(page); + await addToDefaultRequiredFactorsForUser(page, "otp-phone"); + await logout(page); + + await tryEmailPasswordSignIn(page, email); + await completeOTP(page, "PHONE"); + await waitForDashboard(page); + }); }); }); diff --git a/test/end-to-end/mfa.helpers.js b/test/end-to-end/mfa.helpers.js index c2329c360..f39eed3b1 100644 --- a/test/end-to-end/mfa.helpers.js +++ b/test/end-to-end/mfa.helpers.js @@ -45,6 +45,22 @@ export async function setMFAInfo(mfaInfo) { }); assert.strictEqual(resp.status, 200); } + +export async function addToDefaultRequiredFactorsForUser(page, factorId) { + await page.evaluate( + (baseUrl, factorId) => + window.fetch(`${baseUrl}/addRequiredFactor`, { + method: "POST", + headers: new Headers([["content-type", "application/json"]]), + body: JSON.stringify({ + factorId, + }), + }), + TEST_APPLICATION_SERVER_BASE_URL, + factorId + ); +} + export async function completeOTP(page, contactMethod) { await waitForSTElement(page, "[data-supertokens~=input][name=userInputCode]"); diff --git a/test/server/index.js b/test/server/index.js index 7e7cc9c3d..e7fd9971c 100644 --- a/test/server/index.js +++ b/test/server/index.js @@ -448,6 +448,14 @@ app.post("/completeFactor", verifySession(), async (req, res) => { res.send({ status: "OK" }); }); +app.post("/addRequiredFactor", verifySession(), async (req, res) => { + let session = req.session; + + await MultiFactorAuth.addToDefaultRequiredFactorsForUser(session.getUserId(), req.body.factorId); + + res.send({ status: "OK" }); +}); + app.post("/mergeIntoAccessTokenPayload", verifySession(), async (req, res) => { let session = req.session; @@ -1261,22 +1269,6 @@ function initST() { override: { functions: (oI) => ({ ...oI, - getFactorsSetupForUser: async (input) => { - const res = await oI.getFactorsSetupForUser(input); - return mfaInfo?.isAlreadySetup ?? res; - }, - getAllAvailableFactorIds: async (input) => { - const res = await oI.getAllAvailableFactorIds(input); - if (mfaInfo?.isAllowedToSetup || mfaInfo?.isAlreadySetup) { - return [ - ...(mfaInfo.isAllowedToSetup || []), - ...(mfaInfo.isAlreadySetup || []), - "emailpassword", - "thirdparty", - ]; - } - return res; - }, isAllowedToSetupFactor: async (input) => { const res = await oI.isAllowedToSetupFactor(input); if (mfaInfo?.isAllowedToSetup) { @@ -1292,6 +1284,19 @@ function initST() { return res; }, }), + apis: (oI) => ({ + ...oI, + mfaInfoGET: async (input) => { + const res = await oI.mfaInfoGET(input); + + if (res.status === "OK") { + if (mfaInfo.isAlreadySetup) { + res.factors.isAlreadySetup = [...mfaInfo.isAlreadySetup]; + } + } + return res; + }, + }), }, }), ]); diff --git a/test/server/package-lock.json b/test/server/package-lock.json index 4e2622ae9..916136a9e 100644 --- a/test/server/package-lock.json +++ b/test/server/package-lock.json @@ -1042,7 +1042,7 @@ }, "node_modules/supertokens-node": { "version": "16.3.4", - "resolved": "git+ssh://git@github.com/supertokens/supertokens-node.git#24b91929e78ba7d2bccc0750d8efb6d15c3c06bf", + "resolved": "git+ssh://git@github.com/supertokens/supertokens-node.git#37926f17fa8322342d03cff051f9e1d6d1526d15", "license": "Apache-2.0", "dependencies": { "content-type": "^1.0.5", @@ -2013,7 +2013,7 @@ "integrity": "sha512-r0JFBjkMIdep3Lbk3JA+MpnpuOtw4RSyrlRAbrzMcxwiYco3GFWl/daimQZ5b1forOiUODpOlXbSOljP/oyurg==" }, "supertokens-node": { - "version": "git+ssh://git@github.com/supertokens/supertokens-node.git#24b91929e78ba7d2bccc0750d8efb6d15c3c06bf", + "version": "git+ssh://git@github.com/supertokens/supertokens-node.git#37926f17fa8322342d03cff051f9e1d6d1526d15", "from": "supertokens-node@github:supertokens/supertokens-node#mfa-impl", "requires": { "content-type": "^1.0.5",