diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 6f359c95584..237e155427a 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -183,7 +183,7 @@ export default class MainBackground { await this.refreshBadgeAndMenu(true); if (this.systemService != null) { await this.systemService.clearPendingClipboard(); - await this.reloadProcess(); + await this.systemService.startProcessReload(this.authService); } }; @@ -634,7 +634,7 @@ export default class MainBackground { await this.reseedStorage(); this.notificationsService.updateConnection(false); await this.systemService.clearPendingClipboard(); - await this.reloadProcess(); + await this.systemService.startProcessReload(this.authService); } async collectPageDetailsForContentScript(tab: any, sender: string, frameId: number = null) { @@ -1041,16 +1041,4 @@ export default class MainBackground { }); } } - - private async reloadProcess(): Promise { - const accounts = this.stateService.accounts.getValue(); - if (accounts != null) { - for (const userId of Object.keys(accounts)) { - if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) { - return; - } - } - } - await this.systemService.startProcessReload(); - } } diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 6e9da29811c..44b4f400fdb 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -323,7 +323,6 @@ export class NativeMessagingBackground { return; } - await this.stateService.setBiometricLocked(false); this.runtimeBackground.processMessage({ command: "unlocked" }, null, null); } break; diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index 504abbe158f..bc383715ea7 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -107,14 +107,15 @@ export class AppComponent implements OnInit, OnDestroy { this.showToast(msg); }); } else if (msg.command === "reloadProcess") { - const windowReload = + const forceWindowReload = this.platformUtilsService.isSafari() || this.platformUtilsService.isFirefox() || this.platformUtilsService.isOpera(); - if (windowReload) { - // Wait to make sure background has reloaded first. - window.setTimeout(() => BrowserApi.reloadExtension(window), 2000); - } + // Wait to make sure background has reloaded first. + window.setTimeout( + () => BrowserApi.reloadExtension(forceWindowReload ? window : null), + 2000 + ); } else if (msg.command === "reloadPopup") { this.ngZone.run(() => { this.router.navigate(["/"]); diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts index 2f87f5ec4ed..3d9603a48e8 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -293,7 +293,7 @@ export class SettingsComponent implements OnInit { ]); } else { await this.stateService.setBiometricUnlock(null); - await this.stateService.setBiometricLocked(false); + await this.stateService.setBiometricFingerprintValidated(false); } } diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 94f49c07f8d..fe69c820540 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -276,7 +276,6 @@ export class SettingsComponent implements OnInit { if (!newValue || !this.supportsBiometric) { this.biometric = false; await this.stateService.setBiometricUnlock(null); - await this.stateService.setBiometricLocked(false); await this.cryptoService.toggleKey(); return; } @@ -290,7 +289,6 @@ export class SettingsComponent implements OnInit { this.biometric = true; await this.stateService.setBiometricUnlock(true); - await this.stateService.setBiometricLocked(false); await this.cryptoService.toggleKey(); } diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts index ebcc86847a9..e212b6a8191 100644 --- a/apps/desktop/src/app/app.component.ts +++ b/apps/desktop/src/app/app.component.ts @@ -158,7 +158,7 @@ export class AppComponent implements OnInit { this.notificationsService.updateConnection(); this.updateAppMenu(); await this.systemService.clearPendingClipboard(); - await this.reloadProcess(); + await this.systemService.startProcessReload(this.authService); break; case "authBlocked": this.router.navigate(["login"]); @@ -189,7 +189,7 @@ export class AppComponent implements OnInit { this.notificationsService.updateConnection(); await this.updateAppMenu(); await this.systemService.clearPendingClipboard(); - await this.reloadProcess(); + await this.systemService.startProcessReload(this.authService); break; case "reloadProcess": (window.location as any).reload(true); @@ -470,8 +470,6 @@ export class AppComponent implements OnInit { this.keyConnectorService.clear(), ]); - await this.stateService.setBiometricLocked(true, { userId: userBeingLoggedOut }); - if (userBeingLoggedOut === this.activeUserId) { this.searchService.clearIndex(); this.authService.logOut(async () => { @@ -585,21 +583,6 @@ export class AppComponent implements OnInit { } } - private async reloadProcess(): Promise { - const accounts = this.stateService.accounts.getValue(); - if (accounts != null) { - const keys = Object.keys(accounts); - if (keys.length > 0) { - for (const userId of keys) { - if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) { - return; - } - } - } - } - await this.systemService.startProcessReload(); - } - private async checkForSystemTimeout(timeout: number): Promise { for (const userId in this.stateService.accounts.getValue()) { if (userId == null) { diff --git a/libs/angular/src/components/lock.component.ts b/libs/angular/src/components/lock.component.ts index 5ecbb9f8b68..b16717ea7f7 100644 --- a/libs/angular/src/components/lock.component.ts +++ b/libs/angular/src/components/lock.component.ts @@ -237,7 +237,6 @@ export class LockComponent implements OnInit { } private async doContinue() { - await this.stateService.setBiometricLocked(false); await this.stateService.setEverBeenUnlocked(true); const disableFavicon = await this.stateService.getDisableFavicon(); await this.stateService.setDisableFavicon(!!disableFavicon); diff --git a/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts b/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts index 1b26721becd..92eb27de079 100644 --- a/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts +++ b/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts @@ -139,7 +139,6 @@ describe("LogInStrategy", () => { cryptoService.received(1).setEncKey(encKey); cryptoService.received(1).setEncPrivateKey(privateKey); - stateService.received(1).setBiometricLocked(false); messagingService.received(1).send("loggedIn"); }); diff --git a/libs/common/src/abstractions/state.service.ts b/libs/common/src/abstractions/state.service.ts index cf4ddca7eed..ae31a222cca 100644 --- a/libs/common/src/abstractions/state.service.ts +++ b/libs/common/src/abstractions/state.service.ts @@ -53,8 +53,6 @@ export abstract class StateService { setBiometricAwaitingAcceptance: (value: boolean, options?: StorageOptions) => Promise; getBiometricFingerprintValidated: (options?: StorageOptions) => Promise; setBiometricFingerprintValidated: (value: boolean, options?: StorageOptions) => Promise; - getBiometricLocked: (options?: StorageOptions) => Promise; - setBiometricLocked: (value: boolean, options?: StorageOptions) => Promise; getBiometricText: (options?: StorageOptions) => Promise; setBiometricText: (value: string, options?: StorageOptions) => Promise; getBiometricUnlock: (options?: StorageOptions) => Promise; diff --git a/libs/common/src/abstractions/system.service.ts b/libs/common/src/abstractions/system.service.ts index b5c1e5959e3..29953b967b6 100644 --- a/libs/common/src/abstractions/system.service.ts +++ b/libs/common/src/abstractions/system.service.ts @@ -1,5 +1,7 @@ +import { AuthService } from "./auth.service"; + export abstract class SystemService { - startProcessReload: () => Promise; + startProcessReload: (authService: AuthService) => Promise; cancelProcessReload: () => void; clearClipboard: (clipboardValue: string, timeoutMs?: number) => Promise; clearPendingClipboard: () => Promise; diff --git a/libs/common/src/misc/logInStrategies/logIn.strategy.ts b/libs/common/src/misc/logInStrategies/logIn.strategy.ts index a58a7bc8982..8615700681b 100644 --- a/libs/common/src/misc/logInStrategies/logIn.strategy.ts +++ b/libs/common/src/misc/logInStrategies/logIn.strategy.ts @@ -138,7 +138,6 @@ export abstract class LogInStrategy { await this.onSuccessfulLogin(response); - await this.stateService.setBiometricLocked(false); this.messagingService.send("loggedIn"); return result; diff --git a/libs/common/src/models/domain/account.ts b/libs/common/src/models/domain/account.ts index 0c9c32eddcc..88b6de248cb 100644 --- a/libs/common/src/models/domain/account.ts +++ b/libs/common/src/models/domain/account.ts @@ -110,7 +110,6 @@ export class AccountProfile { export class AccountSettings { autoConfirmFingerPrints?: boolean; autoFillOnPageLoadDefault?: boolean; - biometricLocked?: boolean; biometricUnlock?: boolean; clearClipboard?: number; collapsedGroupings?: string[]; diff --git a/libs/common/src/services/state.service.ts b/libs/common/src/services/state.service.ts index c7c5080d99f..bc54c76ffab 100644 --- a/libs/common/src/services/state.service.ts +++ b/libs/common/src/services/state.service.ts @@ -324,24 +324,6 @@ export class StateService< ); } - async getBiometricLocked(options?: StorageOptions): Promise { - return ( - (await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions()))) - ?.settings?.biometricLocked ?? false - ); - } - - async setBiometricLocked(value: boolean, options?: StorageOptions): Promise { - const account = await this.getAccount( - this.reconcileOptions(options, await this.defaultInMemoryOptions()) - ); - account.settings.biometricLocked = value; - await this.saveAccount( - account, - this.reconcileOptions(options, await this.defaultInMemoryOptions()) - ); - } - async getBiometricText(options?: StorageOptions): Promise { return ( await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) diff --git a/libs/common/src/services/stateMigration.service.ts b/libs/common/src/services/stateMigration.service.ts index 034d69f31a2..762f2b89770 100644 --- a/libs/common/src/services/stateMigration.service.ts +++ b/libs/common/src/services/stateMigration.service.ts @@ -255,7 +255,6 @@ export class StateMigrationService< autoFillOnPageLoadDefault: (await this.get(v1Keys.autoFillOnPageLoadDefault)) ?? defaultAccount.settings.autoFillOnPageLoadDefault, - biometricLocked: null, biometricUnlock: (await this.get(v1Keys.biometricUnlock)) ?? defaultAccount.settings.biometricUnlock, diff --git a/libs/common/src/services/system.service.ts b/libs/common/src/services/system.service.ts index 949b8ca40e7..643f00831ce 100644 --- a/libs/common/src/services/system.service.ts +++ b/libs/common/src/services/system.service.ts @@ -1,7 +1,9 @@ +import { AuthService } from "../abstractions/auth.service"; import { MessagingService } from "../abstractions/messaging.service"; import { PlatformUtilsService } from "../abstractions/platformUtils.service"; import { StateService } from "../abstractions/state.service"; import { SystemService as SystemServiceAbstraction } from "../abstractions/system.service"; +import { AuthenticationStatus } from "../enums/authenticationStatus"; import { Utils } from "../misc/utils"; export class SystemService implements SystemServiceAbstraction { @@ -16,35 +18,60 @@ export class SystemService implements SystemServiceAbstraction { private stateService: StateService ) {} - async startProcessReload(): Promise { - if ( - (await this.stateService.getDecryptedPinProtected()) != null || - (await this.stateService.getBiometricLocked()) || - this.reloadInterval != null - ) { - return; - } - this.cancelProcessReload(); - this.reloadInterval = setInterval(async () => { - let doRefresh = false; - const lastActive = await this.stateService.getLastActive(); - if (lastActive != null) { - const diffSeconds = new Date().getTime() - lastActive; - // Don't refresh if they are still active in the window - doRefresh = diffSeconds >= 5000; - } - const biometricLockedFingerprintValidated = - (await this.stateService.getBiometricFingerprintValidated()) && - (await this.stateService.getBiometricLocked()); - if (doRefresh && !biometricLockedFingerprintValidated) { - clearInterval(this.reloadInterval); - this.reloadInterval = null; - this.messagingService.send("reloadProcess"); - if (this.reloadCallback != null) { - await this.reloadCallback(); + async startProcessReload(authService: AuthService): Promise { + const accounts = this.stateService.accounts.getValue(); + if (accounts != null) { + const keys = Object.keys(accounts); + if (keys.length > 0) { + for (const userId of keys) { + if ((await authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) { + return; + } } } - }, 10000); + } + + // A reloadInterval has already been set and is executing + if (this.reloadInterval != null) { + return; + } + + // User has set a PIN, with ask for master password on restart, to protect their vault + const decryptedPinProtected = await this.stateService.getDecryptedPinProtected(); + if (decryptedPinProtected != null) { + return; + } + + this.cancelProcessReload(); + this.reloadInterval = setInterval(async () => await this.executeProcessReload(), 10000); + } + + private async inactiveMoreThanSeconds(seconds: number): Promise { + const lastActive = await this.stateService.getLastActive(); + if (lastActive != null) { + const diffMs = new Date().getTime() - lastActive; + return diffMs >= seconds * 1000; + } + return true; + } + + private async executeProcessReload() { + const accounts = this.stateService.accounts.getValue(); + const doRefresh = + accounts == null || + Object.keys(accounts).length == 0 || + (await this.inactiveMoreThanSeconds(5)); + + const biometricLockedFingerprintValidated = + await this.stateService.getBiometricFingerprintValidated(); + if (doRefresh && !biometricLockedFingerprintValidated) { + clearInterval(this.reloadInterval); + this.reloadInterval = null; + this.messagingService.send("reloadProcess"); + if (this.reloadCallback != null) { + await this.reloadCallback(); + } + } } cancelProcessReload(): void { diff --git a/libs/common/src/services/vaultTimeout.service.ts b/libs/common/src/services/vaultTimeout.service.ts index d087ab4277c..ae94000095c 100644 --- a/libs/common/src/services/vaultTimeout.service.ts +++ b/libs/common/src/services/vaultTimeout.service.ts @@ -84,7 +84,6 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { } await this.stateService.setEverBeenUnlocked(true, { userId: userId }); - await this.stateService.setBiometricLocked(true, { userId: userId }); await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId }); await this.cryptoService.clearKey(false, userId);