From 21f77b6aab03903cbca285de87097131610b2981 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Fri, 30 May 2025 12:04:28 +0200 Subject: [PATCH] Remove legacy biometrics protocol --- .../background/nativeMessaging.background.ts | 55 +---------- .../background-browser-biometrics.service.ts | 92 +++++-------------- .../src/biometrics/biometrics-commands.ts | 4 - 3 files changed, 27 insertions(+), 124 deletions(-) diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index 7172b98d727..03876dba673 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -1,4 +1,4 @@ -import { delay, filter, firstValueFrom, from, map, race, timer } from "rxjs"; +import { firstValueFrom } from "rxjs"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; @@ -11,7 +11,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { Utils } from "@bitwarden/common/platform/misc/utils"; import { EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; -import { KeyService, BiometricStateService, BiometricsCommands } from "@bitwarden/key-management"; +import { KeyService, BiometricStateService } from "@bitwarden/key-management"; import { BrowserApi } from "../platform/browser/browser-api"; @@ -81,9 +81,6 @@ export class NativeMessagingBackground { private messageId = 0; private callbacks = new Map(); - - isConnectedToOutdatedDesktopClient = true; - constructor( private keyService: KeyService, private encryptService: EncryptService, @@ -137,7 +134,6 @@ export class NativeMessagingBackground { // Safari has a bundled native component which is always available, no need to // check if the desktop app is running. if (this.platformUtilsService.isSafari()) { - this.isConnectedToOutdatedDesktopClient = false; connectedCallback(); } @@ -189,14 +185,6 @@ export class NativeMessagingBackground { this.secureChannel.sharedSecret = new SymmetricCryptoKey(decrypted); this.logService.info("[Native Messaging IPC] Secure channel established"); - if ("messageId" in message) { - this.logService.info("[Native Messaging IPC] Non-legacy desktop client"); - this.isConnectedToOutdatedDesktopClient = false; - } else { - this.logService.info("[Native Messaging IPC] Legacy desktop client"); - this.isConnectedToOutdatedDesktopClient = true; - } - this.secureChannel.setupResolve(); break; } @@ -286,29 +274,6 @@ export class NativeMessagingBackground { async callCommand(message: Message): Promise { const messageId = this.messageId++; - if ( - message.command == BiometricsCommands.Unlock || - message.command == BiometricsCommands.IsAvailable - ) { - // TODO remove after 2025.3 - // wait until there is no other callbacks, or timeout - const call = await firstValueFrom( - race( - from([false]).pipe(delay(5000)), - timer(0, 100).pipe( - filter(() => this.callbacks.size === 0), - map(() => true), - ), - ), - ); - if (!call) { - this.logService.info( - `[Native Messaging IPC] Message of type ${message.command} did not get a response before timing out`, - ); - return; - } - } - const callback = new Promise((resolver, rejecter) => { this.callbacks.set(messageId, { resolver, rejecter }); }); @@ -417,22 +382,6 @@ export class NativeMessagingBackground { const messageId = message.messageId; - if ( - message.command == BiometricsCommands.Unlock || - message.command == BiometricsCommands.IsAvailable - ) { - this.logService.info( - `[Native Messaging IPC] Received legacy message of type ${message.command}`, - ); - const messageId: number | undefined = this.callbacks.keys().next().value; - if (messageId != null) { - const resolver = this.callbacks.get(messageId); - this.callbacks.delete(messageId); - resolver!.resolver(message); - } - return; - } - if (this.callbacks.has(messageId)) { const callback = this.callbacks!.get(messageId)!; this.callbacks.delete(messageId); 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 a8a89d45274..ef01ade7390 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 @@ -35,17 +35,10 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { try { await this.ensureConnected(); - if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { - const response = await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.Unlock, - }); - return response.response == "unlocked"; - } else { - const response = await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.AuthenticateWithBiometrics, - }); - return response.response; - } + const response = await this.nativeMessagingBackground().callCommand({ + command: BiometricsCommands.AuthenticateWithBiometrics, + }); + return response.response; } catch (e) { this.logService.info("Biometric authentication failed", e); return false; @@ -60,23 +53,12 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { try { await this.ensureConnected(); - if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { - const response = await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.IsAvailable, - }); - const resp = - response.response == "available" - ? BiometricsStatus.Available - : BiometricsStatus.HardwareUnavailable; - return resp; - } else { - const response = await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.GetBiometricsStatus, - }); + const response = await this.nativeMessagingBackground().callCommand({ + command: BiometricsCommands.GetBiometricsStatus, + }); - if (response.response) { - return response.response; - } + if (response.response) { + return response.response; } return BiometricsStatus.Available; // FIXME: Remove when updating file. Eslint update @@ -90,43 +72,23 @@ 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, - }); - if (response.response == "unlocked") { - 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.keyService.setUserKey(userKey, userId); - // to update badge and other things - this.messagingService.send("switchAccount", { userId }); - return userKey; - } - } else { - return null; + const response = await this.nativeMessagingBackground().callCommand({ + command: BiometricsCommands.UnlockWithBiometricsForUser, + 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.keyService.setUserKey(userKey, userId); + // to update badge and other things + this.messagingService.send("switchAccount", { userId }); + return userKey; } } else { - const response = await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.UnlockWithBiometricsForUser, - 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.keyService.setUserKey(userKey, userId); - // to update badge and other things - this.messagingService.send("switchAccount", { userId }); - return userKey; - } - } else { - return null; - } + return null; } } catch (e) { this.logService.info("Biometric unlock for user failed", e); @@ -140,10 +102,6 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { try { await this.ensureConnected(); - if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) { - return await this.getBiometricsStatus(); - } - return ( await this.nativeMessagingBackground().callCommand({ command: BiometricsCommands.GetBiometricsStatusForUser, @@ -161,7 +119,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService { private async ensureConnected() { if (!this.nativeMessagingBackground().connected) { await this.nativeMessagingBackground().callCommand({ - command: BiometricsCommands.IsAvailable, + command: BiometricsCommands.GetBiometricsStatus, }); } } diff --git a/libs/key-management/src/biometrics/biometrics-commands.ts b/libs/key-management/src/biometrics/biometrics-commands.ts index 1ef31a31fb4..38a666e45e5 100644 --- a/libs/key-management/src/biometrics/biometrics-commands.ts +++ b/libs/key-management/src/biometrics/biometrics-commands.ts @@ -12,8 +12,4 @@ export enum BiometricsCommands { /** Checks whether the biometric unlock can be enabled. */ CanEnableBiometricUnlock = "canEnableBiometricUnlock", - - // legacy - Unlock = "biometricUnlock", - IsAvailable = "biometricUnlockAvailable", }