Skip to content

Commit a860f21

Browse files
quextencoroiuHintonjlf0dev
authored
[PM-24128] New Pin service, using PasswordProtectedKeyEnvelope (#15863)
* fix: broken SDK interface * Fix all compile errors related to uuids * Update usages of sdk to type-safe SDK type * Update sdk version * Update to "toSdk" * Move pin service to km ownership * Run format * Eslint * Fix tsconfig * Fix imports and test * Clean up imports * Pin tmp * Initial version of updated pin service * Add tests * Rename function * Clean up logging * Fix imports * Fix cli build * Fix browser desktop * Fix tests * Attempt to fix * Fix build * Fix tests * Fix browser build * Add missing empty line * Fix linting * Remove non-required change * Missing newline * Re-add comment * Undo change to file * Fix missing empty line * Cleanup * Cleanup * Cleanup * Cleanup * Switch to replaysubject * Add comments * Fix tests * Run prettier * Undo change * Fix browser * Fix circular dependency on browser * Add missing clear ephemeral pin * Address feedback * Update docs * Simplify sdk usage in pin service * Replace with mock sdk * Update sdk * Initialize pin service via unlock instead of listening to keyservice * Cleanup * Fix test * Prevent race condition with userkey not being set * Filter null userkeys * [PM-24124] Pin State Service (#16641) * add pin-state.service * add remaining tests * improve description for clearEphemeralPinState * rename getUserKeyWrappedPin$ to userKeyWrappedPin$ * drop temp variable in setPinState * add new test and remove copied one * Fix dep cycle * Fix tests and remaining build issues * Fix cli build * Add comments about functions not being public API --------- Co-authored-by: Andreas Coroiu <[email protected]> Co-authored-by: Hinton <[email protected]> Co-authored-by: Jake Fink <[email protected]>
1 parent 7015663 commit a860f21

33 files changed

+1557
-976
lines changed

apps/browser/src/auth/popup/settings/account-security.component.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,8 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
311311
.pipe(
312312
concatMap(async (value) => {
313313
const userId = (await firstValueFrom(this.accountService.activeAccount$)).id;
314-
const pinKeyEncryptedUserKey =
315-
(await this.pinService.getPinKeyEncryptedUserKeyPersistent(userId)) ||
316-
(await this.pinService.getPinKeyEncryptedUserKeyEphemeral(userId));
317-
await this.pinService.clearPinKeyEncryptedUserKeyPersistent(userId);
318-
await this.pinService.clearPinKeyEncryptedUserKeyEphemeral(userId);
319-
await this.pinService.storePinKeyEncryptedUserKey(pinKeyEncryptedUserKey, value, userId);
314+
const pin = await this.pinService.getPin(userId);
315+
await this.pinService.setPin(pin, value ? "EPHEMERAL" : "PERSISTENT", userId);
320316
this.refreshTimeoutSettings$.next();
321317
}),
322318
takeUntil(this.destroy$),
@@ -486,7 +482,7 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
486482
}
487483
} else {
488484
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
489-
await this.vaultTimeoutSettingsService.clear(userId);
485+
await this.pinService.unsetPin(userId);
490486
}
491487
}
492488

apps/browser/src/background/main.background.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarde
9898
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/services/key-connector.service";
9999
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
100100
import { MasterPasswordService } from "@bitwarden/common/key-management/master-password/services/master-password.service";
101+
import { PinStateService } from "@bitwarden/common/key-management/pin/pin-state.service.implementation";
101102
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
102103
import { PinService } from "@bitwarden/common/key-management/pin/pin.service.implementation";
103104
import { SecurityStateService } from "@bitwarden/common/key-management/security-state/abstractions/security-state.service";
@@ -709,18 +710,7 @@ export default class MainBackground {
709710

710711
this.kdfConfigService = new DefaultKdfConfigService(this.stateProvider);
711712

712-
this.pinService = new PinService(
713-
this.accountService,
714-
this.cryptoFunctionService,
715-
this.encryptService,
716-
this.kdfConfigService,
717-
this.keyGenerationService,
718-
this.logService,
719-
this.stateProvider,
720-
);
721-
722713
this.keyService = new DefaultKeyService(
723-
this.pinService,
724714
this.masterPasswordService,
725715
this.keyGenerationService,
726716
this.cryptoFunctionService,
@@ -733,6 +723,19 @@ export default class MainBackground {
733723
this.kdfConfigService,
734724
);
735725

726+
const pinStateService = new PinStateService(this.stateProvider);
727+
728+
this.pinService = new PinService(
729+
this.accountService,
730+
this.encryptService,
731+
this.kdfConfigService,
732+
this.keyGenerationService,
733+
this.logService,
734+
this.keyService,
735+
this.sdkService,
736+
pinStateService,
737+
);
738+
736739
this.appIdService = new AppIdService(this.storageService, this.logService);
737740

738741
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
@@ -741,7 +744,7 @@ export default class MainBackground {
741744

742745
this.vaultTimeoutSettingsService = new DefaultVaultTimeoutSettingsService(
743746
this.accountService,
744-
this.pinService,
747+
pinStateService,
745748
this.userDecryptionOptionsService,
746749
this.keyService,
747750
this.tokenService,
@@ -759,6 +762,7 @@ export default class MainBackground {
759762
this.biometricStateService,
760763
this.messagingService,
761764
this.vaultTimeoutSettingsService,
765+
this.pinService,
762766
);
763767

764768
this.apiService = new ApiService(
@@ -1681,9 +1685,9 @@ export default class MainBackground {
16811685
this.keyService.clearKeys(userBeingLoggedOut),
16821686
this.cipherService.clear(userBeingLoggedOut),
16831687
this.folderService.clear(userBeingLoggedOut),
1684-
this.vaultTimeoutSettingsService.clear(userBeingLoggedOut),
16851688
this.biometricStateService.logout(userBeingLoggedOut),
16861689
this.popupViewCacheBackgroundService.clearState(),
1690+
this.pinService.logout(userBeingLoggedOut),
16871691
/* We intentionally do not clear:
16881692
* - autofillSettingsService
16891693
* - badgeSettingsService

apps/browser/src/key-management/biometrics/background-browser-biometrics.service.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { mock } from "jest-mock-extended";
22

3+
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
34
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
45
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
56
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -18,6 +19,7 @@ describe("background browser biometrics service tests", function () {
1819
const biometricStateService = mock<BiometricStateService>();
1920
const messagingService = mock<MessagingService>();
2021
const vaultTimeoutSettingsService = mock<VaultTimeoutSettingsService>();
22+
const pinService = mock<PinServiceAbstraction>();
2123

2224
beforeEach(() => {
2325
jest.resetAllMocks();
@@ -28,6 +30,7 @@ describe("background browser biometrics service tests", function () {
2830
biometricStateService,
2931
messagingService,
3032
vaultTimeoutSettingsService,
33+
pinService,
3134
);
3235
});
3336

apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { combineLatest, timer } from "rxjs";
22
import { filter, concatMap } from "rxjs/operators";
33

4+
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
45
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
56
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
67
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -29,6 +30,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
2930
private biometricStateService: BiometricStateService,
3031
private messagingService: MessagingService,
3132
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
33+
private pinService: PinServiceAbstraction,
3234
) {
3335
super();
3436
// Always connect to the native messaging background if biometrics are enabled, not just when it is used
@@ -101,6 +103,7 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
101103
if (await this.keyService.validateUserKey(userKey, userId)) {
102104
await this.biometricStateService.setBiometricUnlockEnabled(true);
103105
await this.keyService.setUserKey(userKey, userId);
106+
await this.pinService.userUnlocked(userId);
104107
// to update badge and other things
105108
this.messagingService.send("switchAccount", { userId });
106109
return userKey;

apps/browser/src/popup/services/services.module.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ import {
7575
InternalMasterPasswordServiceAbstraction,
7676
MasterPasswordServiceAbstraction,
7777
} from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
78-
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
7978
import {
8079
VaultTimeoutService,
8180
VaultTimeoutStringType,
@@ -271,7 +270,6 @@ const safeProviders: SafeProvider[] = [
271270
safeProvider({
272271
provide: KeyService,
273272
useFactory: (
274-
pinService: PinServiceAbstraction,
275273
masterPasswordService: InternalMasterPasswordServiceAbstraction,
276274
keyGenerationService: KeyGenerationService,
277275
cryptoFunctionService: CryptoFunctionService,
@@ -284,7 +282,6 @@ const safeProviders: SafeProvider[] = [
284282
kdfConfigService: KdfConfigService,
285283
) => {
286284
const keyService = new DefaultKeyService(
287-
pinService,
288285
masterPasswordService,
289286
keyGenerationService,
290287
cryptoFunctionService,
@@ -300,7 +297,6 @@ const safeProviders: SafeProvider[] = [
300297
return keyService;
301298
},
302299
deps: [
303-
PinServiceAbstraction,
304300
InternalMasterPasswordServiceAbstraction,
305301
KeyGenerationService,
306302
CryptoFunctionService,

apps/cli/src/service-container/service-container.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import { MasterPasswordUnlockService } from "@bitwarden/common/key-management/ma
7474
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
7575
import { DefaultMasterPasswordUnlockService } from "@bitwarden/common/key-management/master-password/services/default-master-password-unlock.service";
7676
import { MasterPasswordService } from "@bitwarden/common/key-management/master-password/services/master-password.service";
77+
import { PinStateService } from "@bitwarden/common/key-management/pin/pin-state.service.implementation";
7778
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
7879
import { PinService } from "@bitwarden/common/key-management/pin/pin.service.implementation";
7980
import { SecurityStateService } from "@bitwarden/common/key-management/security-state/abstractions/security-state.service";
@@ -93,7 +94,7 @@ import {
9394
} from "@bitwarden/common/platform/abstractions/environment.service";
9495
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
9596
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
96-
import { KeySuffixOptions, LogLevelType } from "@bitwarden/common/platform/enums";
97+
import { LogLevelType } from "@bitwarden/common/platform/enums";
9798
import { MessageSender } from "@bitwarden/common/platform/messaging";
9899
import {
99100
TaskSchedulerService,
@@ -462,18 +463,7 @@ export class ServiceContainer {
462463
this.accountService,
463464
);
464465

465-
this.pinService = new PinService(
466-
this.accountService,
467-
this.cryptoFunctionService,
468-
this.encryptService,
469-
this.kdfConfigService,
470-
this.keyGenerationService,
471-
this.logService,
472-
this.stateProvider,
473-
);
474-
475466
this.keyService = new KeyService(
476-
this.pinService,
477467
this.masterPasswordService,
478468
this.keyGenerationService,
479469
this.cryptoFunctionService,
@@ -486,6 +476,18 @@ export class ServiceContainer {
486476
this.kdfConfigService,
487477
);
488478

479+
const pinStateService = new PinStateService(this.stateProvider);
480+
this.pinService = new PinService(
481+
this.accountService,
482+
this.encryptService,
483+
this.kdfConfigService,
484+
this.keyGenerationService,
485+
this.logService,
486+
this.keyService,
487+
this.sdkService,
488+
pinStateService,
489+
);
490+
489491
this.masterPasswordUnlockService = new DefaultMasterPasswordUnlockService(
490492
this.masterPasswordService,
491493
this.keyService,
@@ -509,7 +511,7 @@ export class ServiceContainer {
509511

510512
this.vaultTimeoutSettingsService = new DefaultVaultTimeoutSettingsService(
511513
this.accountService,
512-
this.pinService,
514+
pinStateService,
513515
this.userDecryptionOptionsService,
514516
this.keyService,
515517
this.tokenService,
@@ -775,7 +777,7 @@ export class ServiceContainer {
775777
this.folderApiService = new FolderApiService(this.folderService, this.apiService);
776778

777779
const lockedCallback = async (userId: UserId) =>
778-
await this.keyService.clearStoredUserKey(KeySuffixOptions.Auto, userId);
780+
await this.keyService.clearStoredUserKey(userId);
779781

780782
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
781783

apps/desktop/src/app/accounts/settings.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ describe("SettingsComponent", () => {
390390
await component.updatePinHandler(false);
391391

392392
expect(component.form.controls.pin.value).toBe(false);
393-
expect(vaultTimeoutSettingsService.clear).toHaveBeenCalled();
393+
expect(vaultTimeoutSettingsService.clear).not.toHaveBeenCalled();
394394
expect(messagingService.send).toHaveBeenCalledWith("redrawMenu");
395395
});
396396
});

apps/desktop/src/app/accounts/settings.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
588588
this.form.controls.pin.setValue(this.userHasPinSet, { emitEvent: false });
589589
} else {
590590
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
591-
await this.vaultTimeoutSettingsService.clear(userId);
591+
await this.pinService.unsetPin(userId);
592592
}
593593
}
594594

apps/desktop/src/app/app.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
4747
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
4848
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
4949
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
50+
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
5051
import {
5152
VaultTimeout,
5253
VaultTimeoutAction,
@@ -177,6 +178,7 @@ export class AppComponent implements OnInit, OnDestroy {
177178
private readonly destroyRef: DestroyRef,
178179
private readonly documentLangSetter: DocumentLangSetter,
179180
private restrictedItemTypesService: RestrictedItemTypesService,
181+
private pinService: PinServiceAbstraction,
180182
private readonly tokenService: TokenService,
181183
private desktopAutotypeDefaultSettingPolicy: DesktopAutotypeDefaultSettingPolicy,
182184
) {
@@ -692,8 +694,8 @@ export class AppComponent implements OnInit, OnDestroy {
692694
await this.keyService.clearKeys(userBeingLoggedOut);
693695
await this.cipherService.clear(userBeingLoggedOut);
694696
await this.folderService.clear(userBeingLoggedOut);
695-
await this.vaultTimeoutSettingsService.clear(userBeingLoggedOut);
696697
await this.biometricStateService.logout(userBeingLoggedOut);
698+
await this.pinService.logout(userBeingLoggedOut);
697699

698700
await this.stateEventRunnerService.handleEvent("logout", userBeingLoggedOut);
699701

apps/desktop/src/app/services/services.module.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ const safeProviders: SafeProvider[] = [
306306
provide: KeyServiceAbstraction,
307307
useClass: ElectronKeyService,
308308
deps: [
309-
PinServiceAbstraction,
310309
InternalMasterPasswordServiceAbstraction,
311310
KeyGenerationService,
312311
CryptoFunctionServiceAbstraction,

0 commit comments

Comments
 (0)