diff --git a/web/apps/auth/src/pages/auth.tsx b/web/apps/auth/src/pages/auth.tsx index 9c954ab564..a187d5f568 100644 --- a/web/apps/auth/src/pages/auth.tsx +++ b/web/apps/auth/src/pages/auth.tsx @@ -22,7 +22,7 @@ import { import { useBaseContext } from "ente-base/context"; import { isHTTP401Error } from "ente-base/http"; import log from "ente-base/log"; -import { masterKeyFromSessionIfLoggedIn } from "ente-base/session"; +import { masterKeyBytesFromSessionIfLoggedIn } from "ente-base/session"; import { t } from "i18next"; import { useRouter } from "next/router"; import React, { useCallback, useEffect, useState } from "react"; @@ -41,7 +41,7 @@ const Page: React.FC = () => { useEffect(() => { const fetchCodes = async () => { - const masterKey = await masterKeyFromSessionIfLoggedIn(); + const masterKey = await masterKeyBytesFromSessionIfLoggedIn(); if (!masterKey) { stashRedirect("/auth"); void router.push("/"); diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index c1b1f83343..05fcf39bd3 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -32,7 +32,7 @@ import log from "ente-base/log"; import { clearSessionStorage, haveCredentialsInSession, - masterKeyFromSessionIfLoggedIn, + masterKeyBytesFromSessionIfLoggedIn, } from "ente-base/session"; import { FullScreenDropZone } from "ente-gallery/components/FullScreenDropZone"; import { type UploadTypeSelectorIntent } from "ente-gallery/components/Upload"; @@ -561,7 +561,7 @@ const Page: React.FC = () => { showSessionExpiredDialog(); return; } - if (!(await masterKeyFromSessionIfLoggedIn())) { + if (!(await masterKeyBytesFromSessionIfLoggedIn())) { clearSessionStorage(); router.push("/credentials"); return; diff --git a/web/packages/base/session.ts b/web/packages/base/session.ts index 9b2cc1e3c5..edb6c78137 100644 --- a/web/packages/base/session.ts +++ b/web/packages/base/session.ts @@ -1,5 +1,5 @@ import { z } from "zod/v4"; -import { decryptBoxBytes, toB64 } from "./crypto"; +import { decryptBox, decryptBoxBytes } from "./crypto"; /** * Remove all data stored in session storage (data tied to the browser tab). @@ -43,12 +43,29 @@ const SessionKeyData = z.object({ // }; /** - * Return the user's decrypted master key from session storage. + * Return the user's decrypted master key bytes from session storage. * * Precondition: The user should be logged in. */ export const masterKeyFromSession = async () => { - const key = await masterKeyFromSessionIfLoggedIn(); + const key = await masterKeyBytesFromSessionIfLoggedIn(); + if (key) { + return key; + } else { + throw new Error( + "The user's master key was not found in session storage. Likely they are not logged in.", + ); + } +}; + +/** + * Variant of {@link masterKeyFromSession} that returns the master key as a + * base64 string. + * + * TODO(RE): Undup + */ +export const masterKeyB64FromSession = async () => { + const key = await masterKeyB64FromSessionIfLoggedIn(); if (key) { return key; } else { @@ -62,17 +79,18 @@ export const masterKeyFromSession = async () => { * Return `true` if the user's encrypted master key is present in the session. * * Use {@link masterKeyFromSessionIfLoggedIn} to get the actual master key after - * decrypting it. This function is instead useful as a quick check to verify if - * we have credentials at hand or not. + * decrypting it. This function is a similar and quicker check to verify if we + * have credentials at hand or not, but it doesn't attempt to verify that the + * key present in the session can actually be decrypted. */ export const haveCredentialsInSession = () => !!sessionStorage.getItem("encryptionKey"); /** - * Return the decrypted user's master key from session storage if they are - * logged in, otherwise return `undefined`. + * Return the decrypted user's master key (as bytes) from session storage if + * they are logged in, otherwise return `undefined`. */ -export const masterKeyFromSessionIfLoggedIn = async () => { +export const masterKeyBytesFromSessionIfLoggedIn = async () => { // TODO: Same value as the deprecated getKey("encryptionKey") const value = sessionStorage.getItem("encryptionKey"); if (!value) return undefined; @@ -84,10 +102,21 @@ export const masterKeyFromSessionIfLoggedIn = async () => { }; /** - * Variant of {@link masterKeyFromSession} that returns the master key as a - * base64 string. + * Return the decrypted user's master key (as a base64 string) from session + * storage if they are logged in, otherwise return `undefined`. + * + * TODO(RE): Undup. */ -export const masterKeyB64FromSession = () => masterKeyFromSession().then(toB64); +export const masterKeyB64FromSessionIfLoggedIn = async () => { + // TODO: Same value as the deprecated getKey("encryptionKey") + const value = sessionStorage.getItem("encryptionKey"); + if (!value) return undefined; + + const { encryptedData, key, nonce } = SessionKeyData.parse( + JSON.parse(value), + ); + return decryptBox({ encryptedData, nonce }, key); +}; /** * Return the decrypted user's key encryption key ("kek") from session storage