From 014a33373e7190f422d674b18d8d1dd8551fefdd Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 20 Jan 2026 18:14:10 +0100 Subject: [PATCH] Unlock with MP via sdk --- .../src/lock/components/lock.component.ts | 34 ++--------- .../master-password-lock.component.ts | 15 ++--- libs/unlock/src/unlock.service.ts | 59 +++++++++++++++++-- 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/libs/key-management-ui/src/lock/components/lock.component.ts b/libs/key-management-ui/src/lock/components/lock.component.ts index e6d0ee9b622..5642b134386 100644 --- a/libs/key-management-ui/src/lock/components/lock.component.ts +++ b/libs/key-management-ui/src/lock/components/lock.component.ts @@ -55,6 +55,7 @@ import { } from "@bitwarden/key-management"; import { AccountCryptographicStateService } from "@bitwarden/common/key-management/account-cryptography/account-cryptographic-state.service"; +import { UnlockService } from "@bitwarden/unlock"; import { UnlockOption, @@ -179,8 +180,7 @@ export class LockComponent implements OnInit, OnDestroy { private lockComponentService: LockComponentService, private anonLayoutWrapperDataService: AnonLayoutWrapperDataService, private encryptedMigrator: EncryptedMigrator, - private registerSdkService: RegisterSdkService, - private accountCryptographicStateService: AccountCryptographicStateService, + private unlockService: UnlockService, // desktop deps private broadcasterService: BroadcasterService, @@ -491,34 +491,8 @@ export class LockComponent implements OnInit, OnDestroy { const MAX_INVALID_PIN_ENTRY_ATTEMPTS = 5; try { - await firstValueFrom( - this.registerSdkService.registerClient$(this.activeAccount.id).pipe( - map(async (sdk) => { - if (!sdk) { - throw new Error("SDK not available"); - } - using ref = sdk.take(); - return ref.value.crypto().initialize_user_crypto({ - userId: this.activeAccount.id, - kdfParams: { - pBKDF2: { iterations: 100000 } - }, - email: "test@quexten.com", - accountCryptographicState: await firstValueFrom(this.accountCryptographicStateService.accountCryptographicState$(this.activeAccount.id)), - method: { - pinEnvelope: { - pin: pin, - pin_protected_user_key_envelope: await this.pinStateService.getPinProtectedUserKeyEnvelope( - this.activeAccount.id, - "PERSISTENT", - ), - } - } - }); - }), - ) - ); - //const userKey = await this.pinService.decryptUserKeyWithPin(pin, this.activeAccount.id); + this.unlockService.unlockWithPin(this.activeAccount.id, pin); + // Backward compatibility. The user-key is already set const userKey = await firstValueFrom(this.keyService.userKey$(this.activeAccount.id)); if (userKey) { diff --git a/libs/key-management-ui/src/lock/components/master-password-lock/master-password-lock.component.ts b/libs/key-management-ui/src/lock/components/master-password-lock/master-password-lock.component.ts index 1237869717f..ca3932bad3d 100644 --- a/libs/key-management-ui/src/lock/components/master-password-lock/master-password-lock.component.ts +++ b/libs/key-management-ui/src/lock/components/master-password-lock/master-password-lock.component.ts @@ -26,10 +26,11 @@ import { IconButtonModule, ToastService, } from "@bitwarden/components"; -import { BiometricsStatus } from "@bitwarden/key-management"; +import { BiometricsStatus, KeyService } from "@bitwarden/key-management"; import { LogService } from "@bitwarden/logging"; import { CommandDefinition, MessageListener } from "@bitwarden/messaging"; import { UserId } from "@bitwarden/user-core"; +import { UnlockService } from "@bitwarden/unlock"; import { UnlockOption, @@ -52,8 +53,9 @@ import { ], }) export class MasterPasswordLockComponent implements OnInit, OnDestroy { + private readonly unlockService = inject(UnlockService); + private readonly keyService = inject(KeyService); private readonly accountService = inject(AccountService); - private readonly masterPasswordUnlockService = inject(MasterPasswordUnlockService); private readonly i18nService = inject(I18nService); private readonly toastService = inject(ToastService); private readonly logService = inject(LogService); @@ -123,13 +125,12 @@ export class MasterPasswordLockComponent implements OnInit, OnDestroy { private async unlockViaMasterPassword( masterPassword: string, - activeUserId: UserId, + userId: UserId, ): Promise { try { - const userKey = await this.masterPasswordUnlockService.unlockWithMasterPassword( - masterPassword, - activeUserId, - ); + await this.unlockService.unlockWithMasterPassword(userId, masterPassword); + // Backward compatibility, the user-key is already set + const userKey = await firstValueFrom(this.keyService.userKey$(userId)); this.successfulUnlock.emit({ userKey, masterPassword }); } catch (error) { this.logService.error( diff --git a/libs/unlock/src/unlock.service.ts b/libs/unlock/src/unlock.service.ts index 13a07fc8779..5578401dad8 100644 --- a/libs/unlock/src/unlock.service.ts +++ b/libs/unlock/src/unlock.service.ts @@ -1,6 +1,6 @@ import { UserId } from "@bitwarden/common/types/guid"; - -import { PinLockType } from "@bitwarden/common/key-management/pin/pin-lock-type"; +import { DeviceKey } from "@bitwarden/common/types/key"; +import { EncString, UnsignedSharedKey } from "@bitwarden/sdk-internal"; /** * Service for unlocking a user's account with various methods. @@ -11,9 +11,60 @@ export abstract class UnlockService { * * @param userId - The user's id * @param pin - The user's PIN - * @param pinLockType - The type of PIN lock (PERSISTENT or EPHEMERAL) * @throws If the SDK is not available * @throws If the PIN is invalid or decryption fails */ - abstract unlockWithPin(userId: UserId, pin: string, pinLockType: PinLockType): Promise; + abstract unlockWithPin(userId: UserId, pin: string): Promise; + + /** + * Unlocks the user's account using their master password. + * + * @param userId - The user's id + * @param masterPassword - The user's master password + * @throws If the SDK is not available + * @throws If the master password is invalid or decryption fails + */ + abstract unlockWithMasterPassword(userId: UserId, masterPassword: string): Promise; + + /** + * Unlocks the user's account using a device key (trusted device encryption). + * + * @param userId - The user's id + * @param encryptedDevicePrivateKey - The encrypted device private key + * @param encryptedUserKey - The device-protected user key + * @param deviceKey - The device key + * @throws If the SDK is not available + * @throws If decryption fails + */ + abstract unlockWithDeviceKey( + userId: UserId, + encryptedDevicePrivateKey: EncString, + encryptedUserKey: UnsignedSharedKey, + deviceKey: DeviceKey, + ): Promise; + + /** + * Unlocks the user's account using an auth request (passwordless login). + * + * @param userId - The user's id + * @param privateKey - The request private key + * @param protectedUserKey - The protected user key from the auth request + * @throws If the SDK is not available + * @throws If decryption fails + */ + abstract unlockWithAuthRequest( + userId: UserId, + privateKey: string, + protectedUserKey: UnsignedSharedKey, + ): Promise; + + /** + * Unlocks the user's account using a key connector. + * + * @param userId - The user's id + * @param keyConnectorUrl - The URL of the key connector service + * @throws If the SDK is not available + * @throws If the key connector request fails or decryption fails + */ + abstract unlockWithKeyConnector(userId: UserId, keyConnectorUrl: string): Promise; }