1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 17:53:39 +00:00

Ps/pm 5537/move biometric unlock to state providers (#8099)

* Establish biometric unlock enabled in state providers

* Use biometric state service for biometric state values

* Migrate biometricUnlock

* Fixup Dependencies

* linter and import fixes

* Fix injection

* Fix merge

* Use boolean constructor as mapper

* Conform to documented test naming conventions

* Commit documentation suggestion

Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>

* Fix merge commit

* Fix test names

---------

Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>
This commit is contained in:
Matt Gibson
2024-03-01 09:17:06 -06:00
committed by GitHub
parent 53b547de7c
commit 5677d6265e
26 changed files with 443 additions and 79 deletions

View File

@@ -445,12 +445,12 @@ export class SettingsComponent implements OnInit {
try {
if (!enabled || !this.supportsBiometric) {
this.form.controls.biometric.setValue(false, { emitEvent: false });
await this.stateService.setBiometricUnlock(null);
await this.biometricStateService.setBiometricUnlockEnabled(false);
await this.cryptoService.refreshAdditionalKeys();
return;
}
await this.stateService.setBiometricUnlock(true);
await this.biometricStateService.setBiometricUnlockEnabled(true);
if (this.isWindows) {
// Recommended settings for Windows Hello
this.form.controls.requirePasswordOnStart.setValue(true);
@@ -465,7 +465,7 @@ export class SettingsComponent implements OnInit {
const biometricSet = await this.cryptoService.hasUserKeyStored(KeySuffixOptions.Biometric);
this.form.controls.biometric.setValue(biometricSet, { emitEvent: false });
if (!biometricSet) {
await this.stateService.setBiometricUnlock(null);
await this.biometricStateService.setBiometricUnlockEnabled(false);
}
} finally {
this.messagingService.send("redrawMenu");

View File

@@ -172,7 +172,7 @@ export class LockComponent extends BaseLockComponent {
return;
}
if (await this.stateService.getBiometricUnlock()) {
if (await firstValueFrom(this.biometricStateService.biometricUnlockEnabled$)) {
const response = await this.dialogService.openSimpleDialog({
title: { key: "windowsBiometricUpdateWarningTitle" },
content: { key: "windowsBiometricUpdateWarning" },

View File

@@ -73,8 +73,8 @@ describe("electronCryptoService", () => {
encClientKeyHalf.decrypt = jest.fn().mockResolvedValue(decClientKeyHalf);
});
it("sets an Biometric key if getBiometricUnlock is true and the platform supports secure storage", async () => {
stateService.getBiometricUnlock.mockResolvedValue(true);
it("sets a Biometric key if getBiometricUnlock is true and the platform supports secure storage", async () => {
biometricStateService.getBiometricUnlockEnabled.mockResolvedValue(true);
platformUtilService.supportsSecureStorage.mockReturnValue(true);
biometricStateService.getRequirePasswordOnStart.mockResolvedValue(true);
biometricStateService.getEncryptedClientKeyHalf.mockResolvedValue(encClientKeyHalf);
@@ -90,7 +90,7 @@ describe("electronCryptoService", () => {
});
it("clears the Biometric key if getBiometricUnlock is false or the platform does not support secure storage", async () => {
stateService.getBiometricUnlock.mockResolvedValue(true);
biometricStateService.getBiometricUnlockEnabled.mockResolvedValue(true);
platformUtilService.supportsSecureStorage.mockReturnValue(false);
await sut.setUserKey(mockUserKey, mockUserId);

View File

@@ -1,3 +1,5 @@
import { firstValueFrom } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
@@ -97,7 +99,11 @@ export class ElectronCryptoService extends CryptoService {
protected async shouldStoreKey(keySuffix: KeySuffixOptions, userId?: UserId): Promise<boolean> {
if (keySuffix === KeySuffixOptions.Biometric) {
const biometricUnlock = await this.stateService.getBiometricUnlock({ userId: userId });
const biometricUnlockPromise =
userId == null
? firstValueFrom(this.biometricStateService.biometricUnlockEnabled$)
: this.biometricStateService.getBiometricUnlockEnabled(userId);
const biometricUnlock = await biometricUnlockPromise;
return biometricUnlock && this.platformUtilService.supportsSecureStorage();
}
return await super.shouldStoreKey(keySuffix, userId);

View File

@@ -8,10 +8,12 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { BiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service";
import { KeySuffixOptions } from "@bitwarden/common/platform/enums";
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 { UserId } from "@bitwarden/common/types/guid";
import { DialogService } from "@bitwarden/components";
import { BrowserSyncVerificationDialogComponent } from "../app/components/browser-sync-verification-dialog.component";
@@ -36,6 +38,7 @@ export class NativeMessagingService {
private i18nService: I18nService,
private messagingService: MessagingService,
private stateService: StateService,
private biometricStateService: BiometricStateService,
private nativeMessageHandler: NativeMessageHandlerService,
private dialogService: DialogService,
private ngZone: NgZone,
@@ -136,7 +139,11 @@ export class NativeMessagingService {
return this.send({ command: "biometricUnlock", response: "not supported" }, appId);
}
if (!(await this.stateService.getBiometricUnlock({ userId: message.userId }))) {
const biometricUnlockPromise =
message.userId == null
? firstValueFrom(this.biometricStateService.biometricUnlockEnabled$)
: this.biometricStateService.getBiometricUnlockEnabled(message.userId as UserId);
if (!(await biometricUnlockPromise)) {
// 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.send({ command: "biometricUnlock", response: "not enabled" }, appId);