1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-18 02:19:18 +00:00

Remove legacy biometrics protocol

This commit is contained in:
Bernd Schoolmann
2025-05-30 12:04:28 +02:00
parent a02c230e4d
commit 21f77b6aab
3 changed files with 27 additions and 124 deletions

View File

@@ -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<number, Callback>();
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<any> {
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);

View File

@@ -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,
});
}
}

View File

@@ -12,8 +12,4 @@ export enum BiometricsCommands {
/** Checks whether the biometric unlock can be enabled. */
CanEnableBiometricUnlock = "canEnableBiometricUnlock",
// legacy
Unlock = "biometricUnlock",
IsAvailable = "biometricUnlockAvailable",
}