mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
core: add support for fallback hashing
on ios some users using passwords with multi byte characters generates the wrong hash. This commit adds support for fallback to allow those users to continue to login once the fix has been applied.
This commit is contained in:
committed by
Ammar Ahmed
parent
565b0382f9
commit
4b9a95ded7
@@ -136,17 +136,39 @@ class UserManager {
|
|||||||
hashedPassword = await this.db.storage().hash(password, email);
|
hashedPassword = await this.db.storage().hash(password, email);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
let usesFallback = false;
|
||||||
await this.tokenManager.saveToken(
|
await this.tokenManager.saveToken(
|
||||||
await http.post(
|
await http
|
||||||
`${constants.AUTH_HOST}${ENDPOINTS.token}`,
|
.post(
|
||||||
{
|
`${constants.AUTH_HOST}${ENDPOINTS.token}`,
|
||||||
grant_type: "mfa_password",
|
{
|
||||||
client_id: "notesnook",
|
grant_type: "mfa_password",
|
||||||
scope: "notesnook.sync offline_access IdentityServerApi",
|
client_id: "notesnook",
|
||||||
password: hashedPassword
|
scope: "notesnook.sync offline_access IdentityServerApi",
|
||||||
},
|
password: hashedPassword
|
||||||
token.access_token
|
},
|
||||||
)
|
token.access_token
|
||||||
|
)
|
||||||
|
.catch(async (e) => {
|
||||||
|
if (e instanceof Error && e.message === "invalid_grant") {
|
||||||
|
hashedPassword = await this.db
|
||||||
|
.storage()
|
||||||
|
.hash(password, email, { usesFallback: true });
|
||||||
|
if (hashedPassword === null) return Promise.reject(e);
|
||||||
|
usesFallback = true;
|
||||||
|
return await http.post(
|
||||||
|
`${constants.AUTH_HOST}${ENDPOINTS.token}`,
|
||||||
|
{
|
||||||
|
grant_type: "mfa_password",
|
||||||
|
client_id: "notesnook",
|
||||||
|
scope: "notesnook.sync offline_access IdentityServerApi",
|
||||||
|
password: hashedPassword
|
||||||
|
},
|
||||||
|
token.access_token
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.reject(e);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const user = await this.fetchUser();
|
const user = await this.fetchUser();
|
||||||
@@ -157,10 +179,18 @@ class UserManager {
|
|||||||
await this.db.syncer.devices.register();
|
await this.db.syncer.devices.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.db.storage().deriveCryptoKey({
|
if (usesFallback) {
|
||||||
password,
|
await this.db.storage().deriveCryptoKeyFallback({
|
||||||
salt: user.salt
|
password,
|
||||||
});
|
salt: user.salt
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await this.db.storage().deriveCryptoKey({
|
||||||
|
password,
|
||||||
|
salt: user.salt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await this.db.kv().write("usesFallbackPWHash", usesFallback);
|
||||||
EV.publish(EVENTS.userLoggedIn, user);
|
EV.publish(EVENTS.userLoggedIn, user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await this.tokenManager.saveToken(token);
|
await this.tokenManager.saveToken(token);
|
||||||
@@ -301,7 +331,11 @@ class UserManager {
|
|||||||
|
|
||||||
await http.post(
|
await http.post(
|
||||||
`${constants.API_HOST}${ENDPOINTS.deleteUser}`,
|
`${constants.API_HOST}${ENDPOINTS.deleteUser}`,
|
||||||
{ password: await this.db.storage().hash(password, user.email) },
|
{
|
||||||
|
password: await this.db.storage().hash(password, user.email, {
|
||||||
|
usesFallback: await this.db.kv().read("usesFallbackPWHash")
|
||||||
|
})
|
||||||
|
},
|
||||||
token
|
token
|
||||||
);
|
);
|
||||||
await this.logout(false, "Account deleted.");
|
await this.logout(false, "Account deleted.");
|
||||||
@@ -450,7 +484,9 @@ class UserManager {
|
|||||||
{
|
{
|
||||||
type: "change_email",
|
type: "change_email",
|
||||||
new_email: newEmail,
|
new_email: newEmail,
|
||||||
password: await this.db.storage().hash(password, email),
|
password: await this.db.storage().hash(password, email, {
|
||||||
|
usesFallback: await this.db.kv().read("usesFallbackPWHash")
|
||||||
|
}),
|
||||||
verification_code: code
|
verification_code: code
|
||||||
},
|
},
|
||||||
token
|
token
|
||||||
@@ -529,7 +565,9 @@ class UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (old_password)
|
if (old_password)
|
||||||
old_password = await this.db.storage().hash(old_password, email);
|
old_password = await this.db.storage().hash(old_password, email, {
|
||||||
|
usesFallback: await this.db.kv().read("usesFallbackPWHash")
|
||||||
|
});
|
||||||
if (new_password)
|
if (new_password)
|
||||||
new_password = await this.db.storage().hash(new_password, email);
|
new_password = await this.db.storage().hash(new_password, email);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ interface KV {
|
|||||||
deviceId: string;
|
deviceId: string;
|
||||||
lastBackupTime: number;
|
lastBackupTime: number;
|
||||||
fullOfflineMode: boolean;
|
fullOfflineMode: boolean;
|
||||||
|
usesFallbackPWHash: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const KEYS: (keyof KV)[] = [
|
export const KEYS: (keyof KV)[] = [
|
||||||
@@ -40,7 +41,8 @@ export const KEYS: (keyof KV)[] = [
|
|||||||
"monographs",
|
"monographs",
|
||||||
"deviceId",
|
"deviceId",
|
||||||
"lastBackupTime",
|
"lastBackupTime",
|
||||||
"fullOfflineMode"
|
"fullOfflineMode",
|
||||||
|
"usesFallbackPWHash"
|
||||||
];
|
];
|
||||||
|
|
||||||
export class KVStorage {
|
export class KVStorage {
|
||||||
|
|||||||
@@ -58,10 +58,16 @@ export interface IStorage {
|
|||||||
items: Cipher<"base64">[]
|
items: Cipher<"base64">[]
|
||||||
): Promise<string[]>;
|
): Promise<string[]>;
|
||||||
deriveCryptoKey(credentials: SerializedKey): Promise<void>;
|
deriveCryptoKey(credentials: SerializedKey): Promise<void>;
|
||||||
hash(password: string, email: string): Promise<string>;
|
hash(
|
||||||
|
password: string,
|
||||||
|
email: string,
|
||||||
|
options?: { usesFallback?: boolean }
|
||||||
|
): Promise<string>;
|
||||||
getCryptoKey(): Promise<string | undefined>;
|
getCryptoKey(): Promise<string | undefined>;
|
||||||
generateCryptoKey(password: string, salt?: string): Promise<SerializedKey>;
|
generateCryptoKey(password: string, salt?: string): Promise<SerializedKey>;
|
||||||
|
|
||||||
|
deriveCryptoKeyFallback(credentials: SerializedKey): Promise<void>;
|
||||||
|
|
||||||
// async generateRandomKey() {
|
// async generateRandomKey() {
|
||||||
// const passwordBytes = randomBytes(124);
|
// const passwordBytes = randomBytes(124);
|
||||||
// const password = passwordBytes.toString("base64");
|
// const password = passwordBytes.toString("base64");
|
||||||
|
|||||||
Reference in New Issue
Block a user