Log clearer errors when picklekey goes missing (#27)

* tokens.ts: improve documentation

Improve variable naming and documentation on the methods in `tokens.ts`.

* rename restoreFromLocalStorage

Since the session data isn't actually stored in localstorage, this feels like a
misleading name.

* Lifecycle: bail out if picklekey is missing

Currently, if we have an accesstoken which is encrypted with a picklekey, but
the picklekey has gone missing, we carry on with no access token at all. This
is sure to blow up in some way or other later on, but in a rather cryptic way.

Instead, let's bail out early.

(This will produce a "can't restore session" error, but we normally see one of
those anyway because we can't initialise the crypto store.)
This commit is contained in:
Richard van der Hoff 2024-09-11 16:13:04 +01:00 committed by GitHub
parent d337fba76e
commit 433c14e5a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 119 additions and 77 deletions

View file

@ -203,7 +203,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
false,
).then(() => true);
}
const success = await restoreFromLocalStorage({
const success = await restoreSessionFromStorage({
ignoreGuest: Boolean(opts.ignoreGuest),
});
if (success) {
@ -548,17 +548,19 @@ async function abortLogin(): Promise<void> {
}
}
// returns a promise which resolves to true if a session is found in
// localstorage
//
// N.B. Lifecycle.js should not maintain any further localStorage state, we
// are moving towards using SessionStore to keep track of state related
// to the current session (which is typically backed by localStorage).
//
// The plan is to gradually move the localStorage access done here into
// SessionStore to avoid bugs where the view becomes out-of-sync with
// localStorage (e.g. isGuest etc.)
export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): Promise<boolean> {
/** Attempt to restore the session from localStorage or indexeddb.
*
* @returns true if a session was found; false if no existing session was found.
*
* N.B. Lifecycle.js should not maintain any further localStorage state, we
* are moving towards using SessionStore to keep track of state related
* to the current session (which is typically backed by localStorage).
*
* The plan is to gradually move the localStorage access done here into
* SessionStore to avoid bugs where the view becomes out-of-sync with
* localStorage (e.g. isGuest etc.)
*/
export async function restoreSessionFromStorage(opts?: { ignoreGuest?: boolean }): Promise<boolean> {
const ignoreGuest = opts?.ignoreGuest;
if (!localStorage) {
@ -582,10 +584,11 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
if (pickleKey) {
logger.log(`Got pickle key for ${userId}|${deviceId}`);
} else {
logger.log("No pickle key available");
logger.log(`No pickle key available for ${userId}|${deviceId}`);
}
const decryptedAccessToken = await tryDecryptToken(pickleKey, accessToken, ACCESS_TOKEN_IV);
const decryptedRefreshToken = await tryDecryptToken(pickleKey, refreshToken, REFRESH_TOKEN_IV);
const decryptedRefreshToken =
refreshToken && (await tryDecryptToken(pickleKey, refreshToken, REFRESH_TOKEN_IV));
const freshLogin = sessionStorage.getItem("mx_fresh_login") === "true";
sessionStorage.removeItem("mx_fresh_login");
@ -595,7 +598,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
{
userId: userId,
deviceId: deviceId,
accessToken: decryptedAccessToken!,
accessToken: decryptedAccessToken,
refreshToken: decryptedRefreshToken,
homeserverUrl: hsUrl,
identityServerUrl: isUrl,