From e51f9f1e0807ad21a261952881ef122d65011929 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 11 Jun 2024 14:36:10 +0530 Subject: [PATCH 1/2] Allow /passkeys/recover redirect --- web/apps/photos/src/pages/_app.tsx | 8 ++------ web/packages/accounts/services/passkey.ts | 16 ++++------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 5921966f35..a9cfbdb510 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -15,7 +15,6 @@ import { } from "@/next/types/app"; import { AppUpdate } from "@/next/types/ipc"; import { ensure } from "@/utils/ensure"; -import { passkeyAuthenticationFinishRedirect } from "@ente/accounts/services/passkey"; import { Overlay } from "@ente/shared/components/Container"; import DialogBox from "@ente/shared/components/DialogBox"; import { @@ -173,11 +172,8 @@ export default function App({ Component, pageProps }: AppProps) { // the user is logged in. const handleOpenURL = (url: string) => { - if (url.startsWith(passkeyAuthenticationFinishRedirect())) { - router.push(url); - } else { - log.info(`Ignoring unhandled open request for URL ${url}`); - } + if (url.startsWith("ente://app")) router.push(url); + else log.info(`Ignoring unhandled open request for URL ${url}`); }; const showUpdateDialog = (update: AppUpdate) => { diff --git a/web/packages/accounts/services/passkey.ts b/web/packages/accounts/services/passkey.ts index a85f8c1c7c..6b98f75a37 100644 --- a/web/packages/accounts/services/passkey.ts +++ b/web/packages/accounts/services/passkey.ts @@ -12,17 +12,6 @@ import HTTPService from "@ente/shared/network/HTTPService"; import { accountsAppURL, apiOrigin } from "@ente/shared/network/api"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; -/** - * Return a URL that can be passed to the accounts app to serve as the redirect - * back to us on successful passkey authentication. - * - * The returned URL begins with `window.location.origin` and will work both when - * we're running in a web browser (of course), but also in the desktop app - * (See: [Note: Using deeplinks to navigate in desktop app]). - */ -export const passkeyAuthenticationFinishRedirect = () => - `${window.location.origin}/passkeys/finish`; - /** * Redirect user to Ente accounts app to authenticate using their second factor, * a passkey they've configured. @@ -40,7 +29,10 @@ export const redirectUserToPasskeyVerificationFlow = ( passkeySessionID: string, ) => { const clientPackage = clientPackageName[appName]; - const redirect = passkeyAuthenticationFinishRedirect(); + // The returned URL begins with `window.location.origin` and will work both + // when we're running in a web browser, and in our desktop / mobile app. + // See: [Note: Using deeplinks to navigate in desktop app] + const redirect = `${window.location.origin}/passkeys/finish`; const params = new URLSearchParams({ clientPackage, passkeySessionID, From 621d58ec0e90402479b947e5aa894aa98ffac39d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 11 Jun 2024 15:13:58 +0530 Subject: [PATCH 2/2] Pass recovery URL explicitly instead of trying various string mainps --- web/apps/accounts/src/pages/passkeys/verify.tsx | 10 ++++++---- web/apps/accounts/src/services/passkey.ts | 15 ++++++--------- web/packages/accounts/services/passkey.ts | 8 +++++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/web/apps/accounts/src/pages/passkeys/verify.tsx b/web/apps/accounts/src/pages/passkeys/verify.tsx index 0953277d55..a7694e57a2 100644 --- a/web/apps/accounts/src/pages/passkeys/verify.tsx +++ b/web/apps/accounts/src/pages/passkeys/verify.tsx @@ -1,7 +1,6 @@ import { setClientPackageForAuthenticatedRequests } from "@/next/http"; import log from "@/next/log"; import type { TwoFactorAuthorizationResponse } from "@/next/types/credentials"; -import { ensure } from "@/utils/ensure"; import { nullToUndefined } from "@/utils/transform"; import { VerticallyCentered } from "@ente/shared/components/Container"; import EnteButton from "@ente/shared/components/EnteButton"; @@ -129,10 +128,13 @@ const Page = () => { const handleRecover = () => { const searchParams = new URLSearchParams(window.location.search); - const redirect = nullToUndefined(searchParams.get("redirect")); - const redirectURL = new URL(ensure(redirect)); + const recover = nullToUndefined(searchParams.get("recover")); + if (!recover) { + log.error("No recover URL was provided"); + return; + } - redirectToPasskeyRecoverPage(redirectURL); + redirectToPasskeyRecoverPage(new URL(recover)); }; const components: Record = { diff --git a/web/apps/accounts/src/services/passkey.ts b/web/apps/accounts/src/services/passkey.ts index b8951def3a..58adaaa0e1 100644 --- a/web/apps/accounts/src/services/passkey.ts +++ b/web/apps/accounts/src/services/passkey.ts @@ -534,20 +534,17 @@ export const redirectAfterPasskeyAuthentication = async ( }; /** - * Redirect back to the calling app that initiated the passkey authentication, - * navigating the user to a page where they can reset their second factor using + * Redirect back to the app that initiated the passkey authentication, + * navigating the user to a place where they can reset their second factor using * their recovery key (e.g. if they have lost access to their passkey). * * The same considerations mentioned in [Note: Finish passkey flow in the * requesting app] apply to recovery too, which is why we need to redirect back * to the app on whose behalf we're authenticating. * - * @param redirectURL The URL we were meant to redirect to after successful - * passkey authentication. Provided as a calling app as a query parameter. + * @param recoverURL The recovery URL provided as a query parameter by the app + * that called us. */ -export const redirectToPasskeyRecoverPage = (redirectURL: URL) => { - // Extract the origin from the given `redirectURL`, and redirect to the - // `/passkeys/recover` page on that origin. - - window.location.href = `${redirectURL.origin}/passkeys/recover`; +export const redirectToPasskeyRecoverPage = (recoverURL: URL) => { + window.location.href = recoverURL.href; }; diff --git a/web/packages/accounts/services/passkey.ts b/web/packages/accounts/services/passkey.ts index 6b98f75a37..32884c358f 100644 --- a/web/packages/accounts/services/passkey.ts +++ b/web/packages/accounts/services/passkey.ts @@ -29,14 +29,16 @@ export const redirectUserToPasskeyVerificationFlow = ( passkeySessionID: string, ) => { const clientPackage = clientPackageName[appName]; - // The returned URL begins with `window.location.origin` and will work both - // when we're running in a web browser, and in our desktop / mobile app. - // See: [Note: Using deeplinks to navigate in desktop app] + // Using `window.location.origin` will work both when we're running in a web + // browser, and in our desktop app. See: [Note: Using deeplinks to navigate + // in desktop app] const redirect = `${window.location.origin}/passkeys/finish`; + const recover = `${window.location.origin}/passkeys/recover`; const params = new URLSearchParams({ clientPackage, passkeySessionID, redirect, + recover, }); const url = `${accountsAppURL()}/passkeys/verify?${params.toString()}`; // [Note: Passkey verification in the desktop app]