1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-03 17:13:47 +00:00

[PM-25373] Windows native biometric rewrite (#16432)

* Extract windows biometrics v2 changes

Co-authored-by: Bernd Schoolmann <mail@quexten.com>

* Handle TDE edge cases

* Make windows rust code async and fix restoring focus freezes

* Add unit test coverage

---------

Co-authored-by: Bernd Schoolmann <mail@quexten.com>
This commit is contained in:
Thomas Avery
2025-10-20 14:47:15 -05:00
committed by GitHub
parent d2c6757626
commit f65e5d52c2
35 changed files with 1971 additions and 182 deletions

View File

@@ -13,13 +13,9 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
import { FakeAccountService } from "@bitwarden/common/spec";
import { CsprngArray } from "@bitwarden/common/types/csprng";
import { UserId } from "@bitwarden/common/types/guid";
import { DialogService, I18nMockService } from "@bitwarden/components";
import {
KeyService,
BiometricsService,
BiometricStateService,
BiometricsCommands,
} from "@bitwarden/key-management";
import { DialogService } from "@bitwarden/components";
import { KeyService, BiometricsService, BiometricsCommands } from "@bitwarden/key-management";
import { ConfigService } from "@bitwarden/services/config.service";
import { DesktopSettingsService } from "../platform/services/desktop-settings.service";
@@ -47,15 +43,14 @@ describe("BiometricMessageHandlerService", () => {
let keyService: MockProxy<KeyService>;
let encryptService: MockProxy<EncryptService>;
let logService: MockProxy<LogService>;
let configService: MockProxy<ConfigService>;
let messagingService: MockProxy<MessagingService>;
let desktopSettingsService: DesktopSettingsService;
let biometricStateService: BiometricStateService;
let biometricsService: MockProxy<BiometricsService>;
let dialogService: MockProxy<DialogService>;
let accountService: AccountService;
let authService: MockProxy<AuthService>;
let ngZone: MockProxy<NgZone>;
let i18nService: MockProxy<I18nMockService>;
beforeEach(() => {
cryptoFunctionService = mock<CryptoFunctionService>();
@@ -64,14 +59,13 @@ describe("BiometricMessageHandlerService", () => {
logService = mock<LogService>();
messagingService = mock<MessagingService>();
desktopSettingsService = mock<DesktopSettingsService>();
biometricStateService = mock<BiometricStateService>();
configService = mock<ConfigService>();
biometricsService = mock<BiometricsService>();
dialogService = mock<DialogService>();
accountService = new FakeAccountService(accounts);
authService = mock<AuthService>();
ngZone = mock<NgZone>();
i18nService = mock<I18nMockService>();
desktopSettingsService.browserIntegrationEnabled$ = of(false);
desktopSettingsService.browserIntegrationFingerprintEnabled$ = of(false);
@@ -94,7 +88,7 @@ describe("BiometricMessageHandlerService", () => {
cryptoFunctionService.rsaEncrypt.mockResolvedValue(
Utils.fromUtf8ToArray("encrypted") as CsprngArray,
);
configService.getFeatureFlag.mockResolvedValue(false);
service = new BiometricMessageHandlerService(
cryptoFunctionService,
keyService,
@@ -102,13 +96,12 @@ describe("BiometricMessageHandlerService", () => {
logService,
messagingService,
desktopSettingsService,
biometricStateService,
biometricsService,
dialogService,
accountService,
authService,
ngZone,
i18nService,
configService,
);
});
@@ -160,13 +153,12 @@ describe("BiometricMessageHandlerService", () => {
logService,
messagingService,
desktopSettingsService,
biometricStateService,
biometricsService,
dialogService,
accountService,
authService,
ngZone,
i18nService,
configService,
);
});
@@ -511,4 +503,19 @@ describe("BiometricMessageHandlerService", () => {
},
);
});
describe("init", () => {
it("enables Windows v2 biometrics when feature flag enabled", async () => {
configService.getFeatureFlag.mockReturnValue(true);
await service.init();
expect(biometricsService.enableWindowsV2Biometrics).toHaveBeenCalled();
});
it("does not enable Windows v2 biometrics when feature flag disabled", async () => {
configService.getFeatureFlag.mockReturnValue(false);
await service.init();
expect(biometricsService.enableWindowsV2Biometrics).not.toHaveBeenCalled();
});
});
});

View File

@@ -4,25 +4,21 @@ import { combineLatest, concatMap, firstValueFrom } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
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";
import { DialogService } from "@bitwarden/components";
import {
BiometricStateService,
BiometricsCommands,
BiometricsService,
BiometricsStatus,
KeyService,
} from "@bitwarden/key-management";
import { BiometricsCommands, BiometricsStatus, KeyService } from "@bitwarden/key-management";
import { BrowserSyncVerificationDialogComponent } from "../app/components/browser-sync-verification-dialog.component";
import { DesktopBiometricsService } from "../key-management/biometrics/desktop.biometrics.service";
import { LegacyMessage, LegacyMessageWrapper } from "../models/native-messaging";
import { DesktopSettingsService } from "../platform/services/desktop-settings.service";
@@ -82,13 +78,12 @@ export class BiometricMessageHandlerService {
private logService: LogService,
private messagingService: MessagingService,
private desktopSettingService: DesktopSettingsService,
private biometricStateService: BiometricStateService,
private biometricsService: BiometricsService,
private biometricsService: DesktopBiometricsService,
private dialogService: DialogService,
private accountService: AccountService,
private authService: AuthService,
private ngZone: NgZone,
private i18nService: I18nService,
private configService: ConfigService,
) {
combineLatest([
this.desktopSettingService.browserIntegrationEnabled$,
@@ -119,6 +114,19 @@ export class BiometricMessageHandlerService {
private connectedApps: ConnectedApps = new ConnectedApps();
async init() {
this.logService.debug(
"[BiometricMessageHandlerService] Initializing biometric message handler",
);
const windowsV2Enabled = await this.configService.getFeatureFlag(
FeatureFlag.WindowsBiometricsV2,
);
if (windowsV2Enabled) {
await this.biometricsService.enableWindowsV2Biometrics();
}
}
async handleMessage(msg: LegacyMessageWrapper) {
const { appId, message: rawMessage } = msg as LegacyMessageWrapper;