[PM-2772] add flag to deter process reload if cancel is clicked on biometrics (#7350)

* add flag to deter process reload if cancel is clicked on biometrics

* rename flag

* store biometrics cancelled to disk instead of integrating with process reload

* allow auto-prompt when opening app
This commit is contained in:
Jake Fink 2024-01-19 10:08:55 -05:00 committed by GitHub
parent ed101946b4
commit 07af08b893
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 39 additions and 0 deletions

View File

@ -136,6 +136,10 @@ export class LockComponent extends BaseLockComponent {
return; return;
} }
if (await this.stateService.getBiometricPromptCancelled()) {
return;
}
this.biometricAsked = true; this.biometricAsked = true;
if (await ipc.platform.isWindowVisible()) { if (await ipc.platform.isWindowVisible()) {
this.unlockBiometric(); this.unlockBiometric();

View File

@ -89,6 +89,8 @@ export class WindowMain {
// This method will be called when Electron is shutting // This method will be called when Electron is shutting
// down the application. // down the application.
app.on("before-quit", () => { app.on("before-quit", () => {
// Allow biometric to auto-prompt on reload
this.stateService.setBiometricPromptCancelled(false);
this.isQuitting = true; this.isQuitting = true;
}); });

View File

@ -118,6 +118,7 @@ export class LockComponent implements OnInit, OnDestroy {
return; return;
} }
await this.stateService.setBiometricPromptCancelled(true);
const userKey = await this.cryptoService.getUserKeyFromStorage(KeySuffixOptions.Biometric); const userKey = await this.cryptoService.getUserKeyFromStorage(KeySuffixOptions.Biometric);
if (userKey) { if (userKey) {
@ -274,6 +275,7 @@ export class LockComponent implements OnInit, OnDestroy {
private async doContinue(evaluatePasswordAfterUnlock: boolean) { private async doContinue(evaluatePasswordAfterUnlock: boolean) {
await this.stateService.setEverBeenUnlocked(true); await this.stateService.setEverBeenUnlocked(true);
await this.stateService.setBiometricPromptCancelled(false);
this.messagingService.send("unlocked"); this.messagingService.send("unlocked");
if (evaluatePasswordAfterUnlock) { if (evaluatePasswordAfterUnlock) {

View File

@ -177,6 +177,18 @@ export abstract class StateService<T extends Account = Account> {
* @deprecated For migration purposes only, use setUserKeyBiometric instead * @deprecated For migration purposes only, use setUserKeyBiometric instead
*/ */
setCryptoMasterKeyBiometric: (value: BiometricKey, options?: StorageOptions) => Promise<void>; setCryptoMasterKeyBiometric: (value: BiometricKey, options?: StorageOptions) => Promise<void>;
/**
* Gets a flag for if the biometrics process has been cancelled.
* Process reload occurs when biometrics is cancelled, so we store to disk to prevent
* it from reprompting and creating a loop.
*/
getBiometricPromptCancelled: (options?: StorageOptions) => Promise<boolean>;
/**
* Sets a flag for if the biometrics process has been cancelled.
* Process reload occurs when biometrics is cancelled, so we store to disk to prevent
* it from reprompting and creating a loop.
*/
setBiometricPromptCancelled: (value: boolean, options?: StorageOptions) => Promise<void>;
getDecryptedCiphers: (options?: StorageOptions) => Promise<CipherView[]>; getDecryptedCiphers: (options?: StorageOptions) => Promise<CipherView[]>;
setDecryptedCiphers: (value: CipherView[], options?: StorageOptions) => Promise<void>; setDecryptedCiphers: (value: CipherView[], options?: StorageOptions) => Promise<void>;
getDecryptedCollections: (options?: StorageOptions) => Promise<CollectionView[]>; getDecryptedCollections: (options?: StorageOptions) => Promise<CollectionView[]>;

View File

@ -267,6 +267,7 @@ export class AccountSettings {
region?: string; region?: string;
smOnboardingTasks?: Record<string, Record<string, boolean>>; smOnboardingTasks?: Record<string, Record<string, boolean>>;
trustDeviceChoiceForDecryption?: boolean; trustDeviceChoiceForDecryption?: boolean;
biometricPromptCancelled?: boolean;
/** @deprecated July 2023, left for migration purposes*/ /** @deprecated July 2023, left for migration purposes*/
pinProtected?: EncryptionPair<string, EncString> = new EncryptionPair<string, EncString>(); pinProtected?: EncryptionPair<string, EncString> = new EncryptionPair<string, EncString>();

View File

@ -910,6 +910,24 @@ export class StateService<
await this.saveSecureStorageKey(partialKeys.biometricKey, value, options); await this.saveSecureStorageKey(partialKeys.biometricKey, value, options);
} }
async getBiometricPromptCancelled(options?: StorageOptions): Promise<boolean> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
return account?.settings?.biometricPromptCancelled;
}
async setBiometricPromptCancelled(value: boolean, options?: StorageOptions): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
account.settings.biometricPromptCancelled = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
}
@withPrototypeForArrayMembers(CipherView, CipherView.fromJSON) @withPrototypeForArrayMembers(CipherView, CipherView.fromJSON)
async getDecryptedCiphers(options?: StorageOptions): Promise<CipherView[]> { async getDecryptedCiphers(options?: StorageOptions): Promise<CipherView[]> {
return ( return (