From 4555e95323ad2842b46d3b24def2248546cb9419 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 17:06:57 +0100 Subject: [PATCH 01/13] Fix biometrics not working in firefox or windows --- .../settings/account-security.component.ts | 11 +++++- .../browser/src/background/main.background.ts | 12 ++++--- .../background/nativeMessaging.background.ts | 4 +++ .../background-browser-biometrics.service.ts | 36 +++++++++++++++++-- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/apps/browser/src/auth/popup/settings/account-security.component.ts b/apps/browser/src/auth/popup/settings/account-security.component.ts index 3b1727f89ac..1a64d860e45 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.ts +++ b/apps/browser/src/auth/popup/settings/account-security.component.ts @@ -507,7 +507,16 @@ export class AccountSecurityComponent implements OnInit, OnDestroy { const biometricsPromise = async () => { try { - const result = await this.biometricsService.authenticateWithBiometrics(); + const userId = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a) => a.id)), + ); + let result = false; + try { + const userKey = await this.biometricsService.unlockWithBiometricsForUser(userId); + result = await this.keyService.validateUserKey(userKey, userId); + } catch (e) { + result = false; + } // prevent duplicate dialog biometricsResponseReceived = true; diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 4bec3d6cc0a..98f3867e5ff 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -632,11 +632,6 @@ export default class MainBackground { this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider); - this.biometricsService = new BackgroundBrowserBiometricsService( - runtimeNativeMessagingBackground, - this.logService, - ); - this.kdfConfigService = new DefaultKdfConfigService(this.stateProvider); this.pinService = new PinService( @@ -665,6 +660,13 @@ export default class MainBackground { this.kdfConfigService, ); + this.biometricsService = new BackgroundBrowserBiometricsService( + runtimeNativeMessagingBackground, + this.logService, + this.keyService, + this.biometricStateService, + ); + this.appIdService = new AppIdService(this.storageService, this.logService); this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider); diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 116d048d2e8..630e071f64a 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -281,6 +281,7 @@ export class NativeMessagingBackground { }); message.messageId = messageId; try { + this.logService.info("DEBUG: Sending message of type " + message.command); await this.send(message); } catch (e) { this.logService.info( @@ -374,6 +375,8 @@ export class NativeMessagingBackground { return; } + this.logService.info("DEBUG:recv message", message); + const messageId = message.messageId; if ( @@ -391,6 +394,7 @@ export class NativeMessagingBackground { } if (this.callbacks.has(messageId)) { + this.logService.info("[Native Messaging IPC] Received message with a callback", message); this.callbacks.get(messageId).resolver(message); } else { this.logService.info("[Native Messaging IPC] Received message without a callback", message); diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index 8e6fc562d14..4ef3bfc5c4f 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -1,9 +1,17 @@ import { Injectable } from "@angular/core"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; -import { BiometricsService, BiometricsCommands, BiometricsStatus } from "@bitwarden/key-management"; +import { + BiometricsService, + BiometricsCommands, + BiometricsStatus, + KeyService, + BiometricStateService, +} from "@bitwarden/key-management"; import { NativeMessagingBackground } from "../../background/nativeMessaging.background"; import { BrowserApi } from "../../platform/browser/browser-api"; @@ -13,6 +21,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { constructor( private nativeMessagingBackground: () => NativeMessagingBackground, private logService: LogService, + private keyService: KeyService, + private biometricStateService: BiometricStateService, ) { super(); } @@ -75,21 +85,41 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.ensureConnected(); if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { + this.logService.info("Biometric unlock for user outdated", userId); const response = await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.Unlock, }); + this.logService.info("Biometric unlock for user", response); if (response.response == "unlocked") { - return response.userKeyB64; + const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); + const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; + if (this.keyService.validateUserKey(userKey, userId)) { + this.logService.info("validated setting enabled"); + await this.biometricStateService.setBiometricUnlockEnabled(true); + await this.biometricStateService.setFingerprintValidated(true); + this.keyService.setUserKey(userKey, userId); + return userKey; + } } else { return null; } } else { + this.logService.info("Unlock for new user", userId); const response = await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.UnlockWithBiometricsForUser, userId: userId, }); + this.logService.info("Biometric unlock for user1", response); if (response.response) { - return response.userKeyB64; + const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); + const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; + if (this.keyService.validateUserKey(userKey, userId)) { + this.logService.info("validated setting enabled"); + await this.biometricStateService.setBiometricUnlockEnabled(true); + await this.biometricStateService.setFingerprintValidated(true); + this.keyService.setUserKey(userKey, userId); + return userKey; + } } else { return null; } From a7c749759bc287289d02d24e9c58d7847209b3b2 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 17:58:50 +0100 Subject: [PATCH 02/13] Remove logs --- .../background-browser-biometrics.service.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index 4ef3bfc5c4f..cb41dbb5583 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -85,40 +85,34 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.ensureConnected(); if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { - this.logService.info("Biometric unlock for user outdated", userId); const response = await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.Unlock, }); - this.logService.info("Biometric unlock for user", response); if (response.response == "unlocked") { const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; if (this.keyService.validateUserKey(userKey, userId)) { - this.logService.info("validated setting enabled"); await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - return userKey; + return response.userKeyB64; } } else { return null; } } else { - this.logService.info("Unlock for new user", userId); const response = await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.UnlockWithBiometricsForUser, userId: userId, }); - this.logService.info("Biometric unlock for user1", response); if (response.response) { const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; if (this.keyService.validateUserKey(userKey, userId)) { - this.logService.info("validated setting enabled"); await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - return userKey; + return response.userKeyB64; } } else { return null; From c4c6c9784f63b563e653c70fdf527e3e062b061b Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 18:13:23 +0100 Subject: [PATCH 03/13] Update badge after biometric unlock --- .../biometrics/background-browser-biometrics.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index cb41dbb5583..91f17e40497 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -95,6 +95,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); + await BrowserApi.sendMessage("updateBadge"); return response.userKeyB64; } } else { @@ -112,6 +113,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); + await BrowserApi.sendMessage("updateBadge"); return response.userKeyB64; } } else { From f7ec68ffb8521fe13994d084bc93297be59c3f21 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 18:21:09 +0100 Subject: [PATCH 04/13] Add removal todo note --- .../biometrics/background-browser-biometrics.service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index 91f17e40497..6b45914e85f 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -84,6 +84,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { try { await this.ensureConnected(); + // todo remove after 2025.3 if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { const response = await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.Unlock, @@ -95,7 +96,6 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - await BrowserApi.sendMessage("updateBadge"); return response.userKeyB64; } } else { @@ -113,7 +113,6 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - await BrowserApi.sendMessage("updateBadge"); return response.userKeyB64; } } else { From 48c3fcbc4bdacd3423b5bab424bffed9c3531e45 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 18:24:08 +0100 Subject: [PATCH 05/13] Remove debug logging --- apps/browser/src/background/nativeMessaging.background.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 630e071f64a..116d048d2e8 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -281,7 +281,6 @@ export class NativeMessagingBackground { }); message.messageId = messageId; try { - this.logService.info("DEBUG: Sending message of type " + message.command); await this.send(message); } catch (e) { this.logService.info( @@ -375,8 +374,6 @@ export class NativeMessagingBackground { return; } - this.logService.info("DEBUG:recv message", message); - const messageId = message.messageId; if ( @@ -394,7 +391,6 @@ export class NativeMessagingBackground { } if (this.callbacks.has(messageId)) { - this.logService.info("[Native Messaging IPC] Received message with a callback", message); this.callbacks.get(messageId).resolver(message); } else { this.logService.info("[Native Messaging IPC] Received message without a callback", message); From e141a1a438574c33482c5ebf499dfe777b4d1447 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 18:31:44 +0100 Subject: [PATCH 06/13] Fix type warnings --- .../biometrics/background-browser-biometrics.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index 6b45914e85f..012dda6a291 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -80,7 +80,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { } } - async unlockWithBiometricsForUser(userId: UserId): Promise { + async unlockWithBiometricsForUser(userId: UserId): Promise { try { await this.ensureConnected(); @@ -92,7 +92,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { if (response.response == "unlocked") { const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; - if (this.keyService.validateUserKey(userKey, userId)) { + if (await this.keyService.validateUserKey(userKey, userId)) { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); @@ -109,7 +109,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { if (response.response) { const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; - if (this.keyService.validateUserKey(userKey, userId)) { + if (await this.keyService.validateUserKey(userKey, userId)) { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); From 0daad18ffebd839c45e6e97bb75778a075a0a8d6 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 18:47:56 +0100 Subject: [PATCH 07/13] Fix userkey typing in background biometrics service --- apps/browser/src/background/runtime.background.ts | 3 ++- .../biometrics/background-browser-biometrics.service.ts | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index 38bb2ec50c9..cab505f256d 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -195,7 +195,8 @@ export default class RuntimeBackground { return await this.main.biometricsService.getBiometricsStatus(); } case BiometricsCommands.UnlockWithBiometricsForUser: { - return await this.main.biometricsService.unlockWithBiometricsForUser(msg.userId); + const userKey = await this.main.biometricsService.unlockWithBiometricsForUser(msg.userId); + return userKey.keyB64; } case BiometricsCommands.GetBiometricsStatusForUser: { return await this.main.biometricsService.getBiometricsStatusForUser(msg.userId); diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index 012dda6a291..a0f54c58a64 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -80,7 +80,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { } } - async unlockWithBiometricsForUser(userId: UserId): Promise { + async unlockWithBiometricsForUser(userId: UserId): Promise { try { await this.ensureConnected(); @@ -96,7 +96,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - return response.userKeyB64; + return userKey; } } else { return null; @@ -107,13 +107,14 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { userId: userId, }); if (response.response) { + // In case the requesting foreground context dies (popup), the userkey should still be set, so the user is unlocked / the setting should be enabled const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64); const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey; if (await this.keyService.validateUserKey(userKey, userId)) { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); - return response.userKeyB64; + return userKey; } } else { return null; @@ -123,6 +124,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { this.logService.info("Biometric unlock for user failed", e); throw new Error("Biometric unlock failed"); } + + return null; } async getBiometricsStatusForUser(id: UserId): Promise { From b2303957d7af3f252caf0db6384f1aefbe9cfb05 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 13 Jan 2025 19:50:46 +0100 Subject: [PATCH 08/13] Simplify types for userkey in foreground-browser-biometrics and runtime.background.ts --- apps/browser/src/background/runtime.background.ts | 3 +-- .../biometrics/foreground-browser-biometrics.ts | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index cab505f256d..38bb2ec50c9 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -195,8 +195,7 @@ export default class RuntimeBackground { return await this.main.biometricsService.getBiometricsStatus(); } case BiometricsCommands.UnlockWithBiometricsForUser: { - const userKey = await this.main.biometricsService.unlockWithBiometricsForUser(msg.userId); - return userKey.keyB64; + return await this.main.biometricsService.unlockWithBiometricsForUser(msg.userId); } case BiometricsCommands.GetBiometricsStatusForUser: { return await this.main.biometricsService.getBiometricsStatusForUser(msg.userId); diff --git a/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts b/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts index 0235ad5bd9c..43cc25e4dad 100644 --- a/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts +++ b/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts @@ -1,4 +1,3 @@ -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; import { UserKey } from "@bitwarden/common/types/key"; import { BiometricsCommands, BiometricsService, BiometricsStatus } from "@bitwarden/key-management"; @@ -29,13 +28,13 @@ export class ForegroundBrowserBiometricsService extends BiometricsService { async unlockWithBiometricsForUser(userId: UserId): Promise { const response = await BrowserApi.sendMessageWithResponse<{ - result: string; + result: UserKey; error: string; }>(BiometricsCommands.UnlockWithBiometricsForUser, { userId }); if (!response.result) { return null; } - return SymmetricCryptoKey.fromString(response.result) as UserKey; + return response.result; } async getBiometricsStatusForUser(id: UserId): Promise { From e7fc809be36ac9b9e6bda44d28251bb2abfe1241 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 14 Jan 2025 12:22:31 +0100 Subject: [PATCH 09/13] Add process reload logging --- .../services/default-process-reload.service.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/common/src/key-management/services/default-process-reload.service.ts b/libs/common/src/key-management/services/default-process-reload.service.ts index f1c3aed6a58..043a178e7e8 100644 --- a/libs/common/src/key-management/services/default-process-reload.service.ts +++ b/libs/common/src/key-management/services/default-process-reload.service.ts @@ -39,6 +39,9 @@ export class DefaultProcessReloadService implements ProcessReloadServiceAbstract let status = await firstValueFrom(authService.authStatusFor$(userId as UserId)); status = await authService.getAuthStatus(userId); if (status === AuthenticationStatus.Unlocked) { + this.logService.info( + "[Process Reload Service] User unlocked, preventing process reload", + ); return; } } @@ -55,6 +58,9 @@ export class DefaultProcessReloadService implements ProcessReloadServiceAbstract if (userId != null) { const ephemeralPin = await this.pinService.getPinKeyEncryptedUserKeyEphemeral(userId); if (ephemeralPin != null) { + this.logService.info( + "[Process Reload Service] Ephemeral pin active, preventing process reload", + ); return; } } @@ -97,7 +103,12 @@ export class DefaultProcessReloadService implements ProcessReloadServiceAbstract await this.reloadCallback(); } return; + } else { + this.logService.info( + "[Process Reload Service] Desktop ipc fingerprint validated, preventing process reload", + ); } + if (this.reloadInterval == null) { this.reloadInterval = setInterval(async () => await this.executeProcessReload(), 1000); } From 7681357b94fcb425315142adbc6aeeb10f1f654d Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 14 Jan 2025 12:23:42 +0100 Subject: [PATCH 10/13] Fix autoprompt not working when no process reload happened --- .../src/angular/lock/components/lock.component.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/key-management/src/angular/lock/components/lock.component.ts b/libs/key-management/src/angular/lock/components/lock.component.ts index 23f1a7a4330..6c912b0eaae 100644 --- a/libs/key-management/src/angular/lock/components/lock.component.ts +++ b/libs/key-management/src/angular/lock/components/lock.component.ts @@ -307,10 +307,12 @@ export class LockComponent implements OnInit, OnDestroy { (await this.biometricService.getShouldAutopromptNow()) ) { await this.biometricService.setShouldAutopromptNow(false); + + const lastProcessReload = await this.biometricStateService.getLastProcessReload(); if ( - (await this.biometricStateService.getLastProcessReload()) == null || - Date.now() - (await this.biometricStateService.getLastProcessReload()).getTime() > - AUTOPROMPT_BIOMETRICS_PROCESS_RELOAD_DELAY + lastProcessReload == null || + isNaN(lastProcessReload.getTime()) || + Date.now() - lastProcessReload.getTime() > AUTOPROMPT_BIOMETRICS_PROCESS_RELOAD_DELAY ) { await this.unlockViaBiometrics(); } From 90c06f613f510db4e33083632276a9fc6993e4e7 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 14 Jan 2025 12:38:25 +0100 Subject: [PATCH 11/13] Fix biometric unlock badge in mv2 --- apps/browser/src/background/main.background.ts | 1 + .../biometrics/background-browser-biometrics.service.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 98f3867e5ff..5d09122bbd6 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -665,6 +665,7 @@ export default class MainBackground { this.logService, this.keyService, this.biometricStateService, + this.messagingService, ); this.appIdService = new AppIdService(this.storageService, this.logService); diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts index a0f54c58a64..e7b068be84e 100644 --- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts +++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@angular/core"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { UserId } from "@bitwarden/common/types/guid"; @@ -23,6 +24,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { private logService: LogService, private keyService: KeyService, private biometricStateService: BiometricStateService, + private messagingService: MessagingService, ) { super(); } @@ -96,6 +98,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); + // to update badge and other things + this.messagingService.send("switchAccount", { userId }); return userKey; } } else { @@ -114,6 +118,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { await this.biometricStateService.setBiometricUnlockEnabled(true); await this.biometricStateService.setFingerprintValidated(true); this.keyService.setUserKey(userKey, userId); + // to update badge and other things + this.messagingService.send("switchAccount", { userId }); return userKey; } } else { From 89fcc8564b76024ed87d99f6352f0c97b58e61af Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 14 Jan 2025 13:11:44 +0100 Subject: [PATCH 12/13] Fix instant reprompt on firefox lock --- apps/browser/src/popup/app.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index e8a660620a9..7b6e402a90f 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -21,7 +21,7 @@ import { ToastOptions, ToastService, } from "@bitwarden/components"; -import { BiometricStateService } from "@bitwarden/key-management"; +import { BiometricsService, BiometricStateService } from "@bitwarden/key-management"; import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service"; import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service"; @@ -66,6 +66,7 @@ export class AppComponent implements OnInit, OnDestroy { private accountService: AccountService, private animationControlService: AnimationControlService, private biometricStateService: BiometricStateService, + private biometricsService: BiometricsService, ) {} async ngOnInit() { @@ -102,7 +103,7 @@ export class AppComponent implements OnInit, OnDestroy { this.messageListener.allMessages$ .pipe( - tap((msg: any) => { + tap(async (msg: any) => { if (msg.command === "doneLoggingOut") { // TODO: PM-8544 - why do we call logout in the popup after receiving the doneLoggingOut message? Hasn't this already completeted logout? this.authService.logOut(async () => { @@ -119,6 +120,7 @@ export class AppComponent implements OnInit, OnDestroy { msg.command === "locked" && (msg.userId == null || msg.userId == this.activeUserId) ) { + await this.biometricsService.setShouldAutopromptNow(false); // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // eslint-disable-next-line @typescript-eslint/no-floating-promises this.router.navigate(["lock"]); From 6deb3471427d3962aece5c86135ce3c5bfc1fbeb Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 15 Jan 2025 15:04:35 +0100 Subject: [PATCH 13/13] Remove biometrics autoprompt on firefox (#12856) --- .../auth/popup/settings/account-security.component.html | 2 +- .../src/auth/popup/settings/account-security.component.ts | 7 +++++++ .../src/angular/lock/components/lock.component.ts | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/browser/src/auth/popup/settings/account-security.component.html b/apps/browser/src/auth/popup/settings/account-security.component.html index 0f2754b2bf2..8bc28c9754d 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.html +++ b/apps/browser/src/auth/popup/settings/account-security.component.html @@ -20,7 +20,7 @@

{{ "unlockMethods" | i18n }}

{{ biometricUnavailabilityReason }} - +