diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index cfb44c6c36..c3ecb5d3fe 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -632,6 +632,7 @@ export default class MainBackground { this.stateService, this.keyGenerationService, this.encryptService, + this.logService, ); this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider); diff --git a/apps/cli/src/auth/commands/unlock.command.ts b/apps/cli/src/auth/commands/unlock.command.ts index 9d7f7771db..3389d022e5 100644 --- a/apps/cli/src/auth/commands/unlock.command.ts +++ b/apps/cli/src/auth/commands/unlock.command.ts @@ -68,7 +68,7 @@ export class UnlockCommand { return Response.error(e.message); } - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId); await this.keyService.setUserKey(userKey, userId); if (await this.keyConnectorService.getConvertAccountRequired()) { diff --git a/apps/cli/src/service-container/service-container.ts b/apps/cli/src/service-container/service-container.ts index 8d1ad6b2e7..ae627e82e7 100644 --- a/apps/cli/src/service-container/service-container.ts +++ b/apps/cli/src/service-container/service-container.ts @@ -404,6 +404,7 @@ export class ServiceContainer { this.stateService, this.keyGenerationService, this.encryptService, + this.logService, ); this.kdfConfigService = new KdfConfigService(this.stateProvider); diff --git a/apps/web/src/app/auth/settings/change-password.component.ts b/apps/web/src/app/auth/settings/change-password.component.ts index 3406c2d5b6..f5f3e80b6b 100644 --- a/apps/web/src/app/auth/settings/change-password.component.ts +++ b/apps/web/src/app/auth/settings/change-password.component.ts @@ -194,7 +194,7 @@ export class ChangePasswordComponent HashPurpose.LocalAuthorization, ); - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId); if (userKey == null) { this.toastService.showToast({ variant: "error", diff --git a/libs/angular/src/auth/components/lock.component.ts b/libs/angular/src/auth/components/lock.component.ts index bc9c667bc8..ce41002985 100644 --- a/libs/angular/src/auth/components/lock.component.ts +++ b/libs/angular/src/auth/components/lock.component.ts @@ -267,6 +267,7 @@ export class LockComponent implements OnInit, OnDestroy { const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( response.masterKey, + userId, ); await this.setUserKeyAndContinue(userKey, userId, true); } diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 5d8822866d..5bf81761ed 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -921,7 +921,13 @@ const safeProviders: SafeProvider[] = [ safeProvider({ provide: InternalMasterPasswordServiceAbstraction, useClass: MasterPasswordService, - deps: [StateProvider, StateServiceAbstraction, KeyGenerationServiceAbstraction, EncryptService], + deps: [ + StateProvider, + StateServiceAbstraction, + KeyGenerationServiceAbstraction, + EncryptService, + LogService, + ], }), safeProvider({ provide: MasterPasswordServiceAbstraction, diff --git a/libs/auth/src/angular/lock/lock.component.ts b/libs/auth/src/angular/lock/lock.component.ts index 3d4bf51e80..94c226f3f6 100644 --- a/libs/auth/src/angular/lock/lock.component.ts +++ b/libs/auth/src/angular/lock/lock.component.ts @@ -483,6 +483,7 @@ export class LockV2Component implements OnInit, OnDestroy { const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( masterPasswordVerificationResponse.masterKey, + this.activeAccount.id, ); await this.setUserKeyAndContinue(userKey, true); } diff --git a/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts b/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts index 3f7e107fa9..a3e2fda2f2 100644 --- a/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts @@ -114,7 +114,10 @@ export class AuthRequestLoginStrategy extends LoginStrategy { private async trySetUserKeyWithMasterKey(userId: UserId): Promise { const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId)); if (masterKey) { - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( + masterKey, + userId, + ); await this.keyService.setUserKey(userKey, userId); } } diff --git a/libs/auth/src/common/login-strategies/password-login.strategy.ts b/libs/auth/src/common/login-strategies/password-login.strategy.ts index 55e869e822..05faef1ba1 100644 --- a/libs/auth/src/common/login-strategies/password-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/password-login.strategy.ts @@ -183,7 +183,10 @@ export class PasswordLoginStrategy extends LoginStrategy { const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId)); if (masterKey) { - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( + masterKey, + userId, + ); await this.keyService.setUserKey(userKey, userId); } } diff --git a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts index d9827c2e28..7b5ad4a31b 100644 --- a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts @@ -496,7 +496,7 @@ describe("SsoLoginStrategy", () => { expect(masterPasswordService.mock.decryptUserKeyWithMasterKey).toHaveBeenCalledWith( masterKey, - undefined, + userId, undefined, ); expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId); @@ -552,7 +552,7 @@ describe("SsoLoginStrategy", () => { expect(masterPasswordService.mock.decryptUserKeyWithMasterKey).toHaveBeenCalledWith( masterKey, - undefined, + userId, undefined, ); expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId); diff --git a/libs/auth/src/common/login-strategies/sso-login.strategy.ts b/libs/auth/src/common/login-strategies/sso-login.strategy.ts index d2660eef8a..b1dffea9b5 100644 --- a/libs/auth/src/common/login-strategies/sso-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/sso-login.strategy.ts @@ -338,7 +338,7 @@ export class SsoLoginStrategy extends LoginStrategy { return; } - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId); await this.keyService.setUserKey(userKey, userId); } diff --git a/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts index 14fafcb58c..07d06a7567 100644 --- a/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/user-api-login.strategy.spec.ts @@ -213,7 +213,7 @@ describe("UserApiLoginStrategy", () => { expect(masterPasswordService.mock.decryptUserKeyWithMasterKey).toHaveBeenCalledWith( masterKey, - undefined, + userId, undefined, ); expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId); diff --git a/libs/auth/src/common/login-strategies/user-api-login.strategy.ts b/libs/auth/src/common/login-strategies/user-api-login.strategy.ts index 4ae95fdbc7..1097e8e04c 100644 --- a/libs/auth/src/common/login-strategies/user-api-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/user-api-login.strategy.ts @@ -69,7 +69,10 @@ export class UserApiLoginStrategy extends LoginStrategy { if (response.apiUseKeyConnector) { const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId)); if (masterKey) { - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( + masterKey, + userId, + ); await this.keyService.setUserKey(userKey, userId); } } diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index a4f1d5d972..86b2a1dd3b 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -200,7 +200,7 @@ describe("AuthRequestService", () => { ); expect(masterPasswordService.mock.decryptUserKeyWithMasterKey).toHaveBeenCalledWith( mockDecryptedMasterKey, - undefined, + mockUserId, undefined, ); expect(keyService.setUserKey).toHaveBeenCalledWith(mockDecryptedUserKey, mockUserId); diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.ts b/libs/auth/src/common/services/auth-request/auth-request.service.ts index 0e416a4a25..b6a7bfb26b 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.ts @@ -150,7 +150,7 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { ); // Decrypt and set user key in state - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey); + const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId); // Set masterKey + masterKeyHash in state after decryption (in case decryption fails) await this.masterPasswordService.setMasterKey(masterKey, userId); diff --git a/libs/auth/src/common/services/pin/pin.service.implementation.ts b/libs/auth/src/common/services/pin/pin.service.implementation.ts index 39bb80e0b7..2a01802fa5 100644 --- a/libs/auth/src/common/services/pin/pin.service.implementation.ts +++ b/libs/auth/src/common/services/pin/pin.service.implementation.ts @@ -418,6 +418,7 @@ export class PinService implements PinServiceAbstraction { const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( masterKey, + userId, encUserKey ? new EncString(encUserKey) : undefined, ); diff --git a/libs/common/src/auth/abstractions/master-password.service.abstraction.ts b/libs/common/src/auth/abstractions/master-password.service.abstraction.ts index bd4d73a0f2..c3a0f135a0 100644 --- a/libs/common/src/auth/abstractions/master-password.service.abstraction.ts +++ b/libs/common/src/auth/abstractions/master-password.service.abstraction.ts @@ -33,16 +33,16 @@ export abstract class MasterPasswordServiceAbstraction { /** * Decrypts the user key with the provided master key * @param masterKey The user's master key + * * @param userId The desired user * @param userKey The user's encrypted symmetric key - * @param userId The desired user * @throws If either the MasterKey or UserKey are not resolved, or if the UserKey encryption type * is neither AesCbc256_B64 nor AesCbc256_HmacSha256_B64 * @returns The user key */ abstract decryptUserKeyWithMasterKey: ( masterKey: MasterKey, + userId: string, userKey?: EncString, - userId?: string, ) => Promise; } diff --git a/libs/common/src/auth/services/master-password/fake-master-password.service.ts b/libs/common/src/auth/services/master-password/fake-master-password.service.ts index f57614f5d5..0357018e61 100644 --- a/libs/common/src/auth/services/master-password/fake-master-password.service.ts +++ b/libs/common/src/auth/services/master-password/fake-master-password.service.ts @@ -64,9 +64,9 @@ export class FakeMasterPasswordService implements InternalMasterPasswordServiceA decryptUserKeyWithMasterKey( masterKey: MasterKey, + userId: string, userKey?: EncString, - userId?: string, ): Promise { - return this.mock.decryptUserKeyWithMasterKey(masterKey, userKey, userId); + return this.mock.decryptUserKeyWithMasterKey(masterKey, userId, userKey); } } diff --git a/libs/common/src/auth/services/master-password/master-password.service.ts b/libs/common/src/auth/services/master-password/master-password.service.ts index e20c8c00e6..3a565e1c78 100644 --- a/libs/common/src/auth/services/master-password/master-password.service.ts +++ b/libs/common/src/auth/services/master-password/master-password.service.ts @@ -1,5 +1,7 @@ import { firstValueFrom, map, Observable } from "rxjs"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; + import { EncryptService } from "../../../platform/abstractions/encrypt.service"; import { KeyGenerationService } from "../../../platform/abstractions/key-generation.service"; import { StateService } from "../../../platform/abstractions/state.service"; @@ -55,6 +57,7 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr private stateService: StateService, private keyGenerationService: KeyGenerationService, private encryptService: EncryptService, + private logService: LogService, ) {} masterKey$(userId: UserId): Observable { @@ -149,10 +152,9 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr async decryptUserKeyWithMasterKey( masterKey: MasterKey, + userId: UserId, userKey?: EncString, - userId?: UserId, ): Promise { - userId ??= await firstValueFrom(this.stateProvider.activeUserId$); userKey ??= await this.getMasterKeyEncryptedUserKey(userId); masterKey ??= await firstValueFrom(this.masterKey$(userId)); @@ -185,6 +187,7 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr } if (decUserKey == null) { + this.logService.warning("Failed to decrypt user key with master key."); return null; }