From da8326229c3743bfae147aa80c2f262bc6cfbca1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Sat, 28 Sep 2024 09:32:25 +0530 Subject: [PATCH 1/4] [web] Redirect to password input on no-email-MFA + new tab Fixes the following bug report, for a user who has email verification disabled: > and about verify in new tab... > it happens when u r at password page after entering email and opening ente.auth.io in new tab opens the verify page instead of password --- web/apps/photos/src/pages/index.tsx | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/web/apps/photos/src/pages/index.tsx b/web/apps/photos/src/pages/index.tsx index 635685b7e3..201a514a2e 100644 --- a/web/apps/photos/src/pages/index.tsx +++ b/web/apps/photos/src/pages/index.tsx @@ -1,5 +1,6 @@ import { Login } from "@/accounts/components/Login"; import { SignUp } from "@/accounts/components/SignUp"; +import type { SRPAttributes } from "@/accounts/types/srp"; import log from "@/base/log"; import { albumsAppOrigin, customAPIHost } from "@/base/origins"; import { DevSettings } from "@/new/photos/components/DevSettings"; @@ -89,7 +90,26 @@ export default function LandingPage() { if (key && token) { await router.push(PAGES.GALLERY); } else if (user?.email) { - await router.push(PAGES.VERIFY); + // The user had previously entered their email on the login screen + // but closed the tab before proceeding (or opened a us in a new tab + // at this point). + // + // In such cases, we'll have an email present. + // + // Where to go next depends on whether they have enabled email + // verification or not. + // + // The login page would have fetched and saved SRP attributes, so we + // can see if they are present and indicate the email verification + // is not required. Otherwise, move to the verification page. + const srpAttributes: SRPAttributes = getData( + LS_KEYS.SRP_ATTRIBUTES, + ); + if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { + await router.push(PAGES.CREDENTIALS); + } else { + await router.push(PAGES.VERIFY); + } } await initLocalForage(); setLoading(false); From 08f84c9cf8f27501dfeb218ec374f4e05a32488a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Sat, 28 Sep 2024 09:54:51 +0530 Subject: [PATCH 2/4] Also handle for auth --- web/apps/photos/src/pages/index.tsx | 22 +--------------------- web/packages/accounts/pages/verify.tsx | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/web/apps/photos/src/pages/index.tsx b/web/apps/photos/src/pages/index.tsx index 201a514a2e..635685b7e3 100644 --- a/web/apps/photos/src/pages/index.tsx +++ b/web/apps/photos/src/pages/index.tsx @@ -1,6 +1,5 @@ import { Login } from "@/accounts/components/Login"; import { SignUp } from "@/accounts/components/SignUp"; -import type { SRPAttributes } from "@/accounts/types/srp"; import log from "@/base/log"; import { albumsAppOrigin, customAPIHost } from "@/base/origins"; import { DevSettings } from "@/new/photos/components/DevSettings"; @@ -90,26 +89,7 @@ export default function LandingPage() { if (key && token) { await router.push(PAGES.GALLERY); } else if (user?.email) { - // The user had previously entered their email on the login screen - // but closed the tab before proceeding (or opened a us in a new tab - // at this point). - // - // In such cases, we'll have an email present. - // - // Where to go next depends on whether they have enabled email - // verification or not. - // - // The login page would have fetched and saved SRP attributes, so we - // can see if they are present and indicate the email verification - // is not required. Otherwise, move to the verification page. - const srpAttributes: SRPAttributes = getData( - LS_KEYS.SRP_ATTRIBUTES, - ); - if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { - await router.push(PAGES.CREDENTIALS); - } else { - await router.push(PAGES.VERIFY); - } + await router.push(PAGES.VERIFY); } await initLocalForage(); setLoading(false); diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index 1fd0d094e1..f56aa57d49 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -42,7 +42,7 @@ import { import { unstashRedirect } from "../services/redirect"; import { configureSRP } from "../services/srp"; import type { PageProps } from "../types/page"; -import type { SRPSetupAttributes } from "../types/srp"; +import type { SRPAttributes, SRPSetupAttributes } from "../types/srp"; const Page: React.FC = ({ appContext }) => { const { logout, showNavBar, setDialogBoxAttributesV2 } = appContext; @@ -69,7 +69,26 @@ const Page: React.FC = ({ appContext }) => { ) { router.push(PAGES.CREDENTIALS); } else { - setEmail(user.email); + // The user might have email verification disabled, but after + // previously entering their email on the login screen, they + // might've closed the tab before proceeding (or opened a us in + // a new tab at this point). + // + // In such cases, we'll end up here with an email present. + // + // To distinguish this scenario from the normal email + // verification flow, we can check to see the SRP attributes + // (the login page would've fetched and saved them). If they are + // present and indicate that email verification is not required, + // redirect to the password verification page. + const srpAttributes: SRPAttributes = getData( + LS_KEYS.SRP_ATTRIBUTES, + ); + if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { + router.push(PAGES.CREDENTIALS); + } else { + setEmail(user.email); + } } }; main(); From 1eb5eaece95a060bb742a34f53142d3070db57b6 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Sat, 28 Sep 2024 10:08:11 +0530 Subject: [PATCH 3/4] Freshness check --- web/packages/accounts/pages/verify.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index f56aa57d49..924d210b08 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -33,6 +33,7 @@ import { t } from "i18next"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import { Trans } from "react-i18next"; +import { getSRPAttributes } from "../api/srp"; import { putAttributes, sendOtt, verifyOtt } from "../api/user"; import { PAGES } from "../constants/pages"; import { @@ -85,7 +86,18 @@ const Page: React.FC = ({ appContext }) => { LS_KEYS.SRP_ATTRIBUTES, ); if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { - router.push(PAGES.CREDENTIALS); + // Fetch the latest SRP attributes instead of relying on the + // potentially stale stored values. This is an infrequent scenario + // path, so extra API calls are fine. + const latestSRPAttributes = await getSRPAttributes(email); + if ( + latestSRPAttributes && + !latestSRPAttributes.isEmailMFAEnabled + ) { + router.push(PAGES.CREDENTIALS); + } else { + setEmail(user.email); + } } else { setEmail(user.email); } From 3288f3250b0af5d531bc1d2d142d47f6a6e74f30 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Sat, 28 Sep 2024 10:14:49 +0530 Subject: [PATCH 4/4] Extract --- web/packages/accounts/pages/verify.tsx | 87 ++++++++++++++------------ 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index 924d210b08..98a54adf8e 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -59,48 +59,11 @@ const Page: React.FC = ({ appContext }) => { useEffect(() => { const main = async () => { const user: User = getData(LS_KEYS.USER); - const keyAttributes: KeyAttributes = getData( - LS_KEYS.KEY_ATTRIBUTES, - ); - if (!user?.email) { - router.push("/"); - } else if ( - keyAttributes?.encryptedKey && - (user.token || user.encryptedToken) - ) { - router.push(PAGES.CREDENTIALS); + const redirect = await redirectionIfNeeded(user); + if (redirect) { + router.push(redirect); } else { - // The user might have email verification disabled, but after - // previously entering their email on the login screen, they - // might've closed the tab before proceeding (or opened a us in - // a new tab at this point). - // - // In such cases, we'll end up here with an email present. - // - // To distinguish this scenario from the normal email - // verification flow, we can check to see the SRP attributes - // (the login page would've fetched and saved them). If they are - // present and indicate that email verification is not required, - // redirect to the password verification page. - const srpAttributes: SRPAttributes = getData( - LS_KEYS.SRP_ATTRIBUTES, - ); - if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { - // Fetch the latest SRP attributes instead of relying on the - // potentially stale stored values. This is an infrequent scenario - // path, so extra API calls are fine. - const latestSRPAttributes = await getSRPAttributes(email); - if ( - latestSRPAttributes && - !latestSRPAttributes.isEmailMFAEnabled - ) { - router.push(PAGES.CREDENTIALS); - } else { - setEmail(user.email); - } - } else { - setEmail(user.email); - } + setEmail(user.email); } }; main(); @@ -284,3 +247,45 @@ const Page: React.FC = ({ appContext }) => { }; export default Page; + +/** + * A function called during page load to see if a redirection is required + * + * @returns The slug to redirect to, if needed. + */ +const redirectionIfNeeded = async (user: User | undefined) => { + const email = user?.email; + if (!email) { + return "/"; + } + + const keyAttributes: KeyAttributes = getData(LS_KEYS.KEY_ATTRIBUTES); + + if (keyAttributes?.encryptedKey && (user.token || user.encryptedToken)) { + return PAGES.CREDENTIALS; + } + + // The user might have email verification disabled, but after previously + // entering their email on the login screen, they might've closed the tab + // before proceeding (or opened a us in a new tab at this point). + // + // In such cases, we'll end up here with an email present. + // + // To distinguish this scenario from the normal email verification flow, we + // can check to see the SRP attributes (the login page would've fetched and + // saved them). If they are present and indicate that email verification is + // not required, redirect to the password verification page. + + const srpAttributes: SRPAttributes = getData(LS_KEYS.SRP_ATTRIBUTES); + if (srpAttributes && !srpAttributes.isEmailMFAEnabled) { + // Fetch the latest SRP attributes instead of relying on the potentially + // stale stored values. This is an infrequent scenario path, so extra + // API calls are fine. + const latestSRPAttributes = await getSRPAttributes(email); + if (latestSRPAttributes && !latestSRPAttributes.isEmailMFAEnabled) { + return PAGES.CREDENTIALS; + } + } + + return undefined; +};