This commit is contained in:
Manav Rathi
2025-06-03 14:42:33 +05:30
parent 97314b7dc1
commit 7cdef46385
2 changed files with 43 additions and 26 deletions

View File

@@ -61,13 +61,6 @@ export interface UpdatedKey {
opsLimit: number;
}
export interface RecoveryKey {
masterKeyEncryptedWithRecoveryKey: string;
masterKeyDecryptionNonce: string;
recoveryKeyEncryptedWithMasterKey: string;
recoveryKeyDecryptionNonce: string;
}
/**
* Ask remote to send a OTP / OTT to the given email to verify that the user has
* access to it. Subsequent the app will pass this OTT back via the
@@ -311,10 +304,28 @@ export const enableTwoFactor = async (req: EnableTwoFactorRequest) =>
}),
);
export const setRecoveryKey = async (token: string, recoveryKey: RecoveryKey) =>
HTTPService.put(
await apiURL("/users/recovery-key"),
recoveryKey,
undefined,
{ "X-Auth-Token": token },
export interface RecoveryKeyAttributes {
masterKeyEncryptedWithRecoveryKey: string;
masterKeyDecryptionNonce: string;
recoveryKeyEncryptedWithMasterKey: string;
recoveryKeyDecryptionNonce: string;
}
/**
* Update the encrypted recovery key attributes for the logged in user.
*
* In practice, this is not expected to be called and is meant as a rare
* fallback for very old accounts created prior to recovery key related
* attributes being assigned on account setup. Even for these, it'll be called
* only once.
*/
export const putUserRecoveryKeyAttributes = async (
recoveryKeyAttributes: RecoveryKeyAttributes,
) =>
ensureOk(
await fetch(await apiURL("/users/recovery-key"), {
method: "PUT",
headers: await authenticatedRequestHeaders(),
body: JSON.stringify(recoveryKeyAttributes),
}),
);

View File

@@ -1,9 +1,8 @@
import { setRecoveryKey } from "ente-accounts/services/user";
import { putUserRecoveryKeyAttributes } from "ente-accounts/services/user";
import { sharedCryptoWorker } from "ente-base/crypto";
import log from "ente-base/log";
import { masterKeyFromSession } from "ente-base/session";
import { getData, setData, setLSUser } from "ente-shared/storage/localStorage";
import { getToken } from "ente-shared/storage/localStorage/helpers";
import { type SessionKey, setKey } from "ente-shared/storage/sessionStorage";
import { getActualKey } from "ente-shared/user";
import type { KeyAttributes } from "ente-shared/user/types";
@@ -141,10 +140,16 @@ export const getRecoveryKey = async () => {
}
};
// Used only for legacy users for whom we did not generate recovery keys during
// sign up
// @returns a new base64 encoded recovery key.
async function createNewRecoveryKey() {
/**
* Generate a new recovery key, tell remote about it, update our local state,
* and then return it.
*
* This function will be used only for legacy users for whom we did not generate
* recovery keys during sign up.
*
* @returns a new base64 encoded recovery key.
*/
const createNewRecoveryKey = async () => {
const masterKey = await getActualKey();
const existingAttributes = getData("keyAttributes");
@@ -159,22 +164,23 @@ async function createNewRecoveryKey() {
recoveryKey,
masterKey,
);
const recoveryKeyAttributes = {
masterKeyEncryptedWithRecoveryKey: encryptedMasterKey.encryptedData,
masterKeyDecryptionNonce: encryptedMasterKey.nonce,
recoveryKeyEncryptedWithMasterKey: encryptedRecoveryKey.encryptedData,
recoveryKeyDecryptionNonce: encryptedRecoveryKey.nonce,
};
await setRecoveryKey(getToken(), recoveryKeyAttributes);
const updatedKeyAttributes = Object.assign(
existingAttributes,
recoveryKeyAttributes,
);
setData("keyAttributes", updatedKeyAttributes);
await putUserRecoveryKeyAttributes(recoveryKeyAttributes);
setData("keyAttributes", {
...existingAttributes,
...recoveryKeyAttributes,
});
return recoveryKey;
}
};
/**
* Decrypt the {@link encryptedChallenge} sent by remote during the delete