diff --git a/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.spec.ts b/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.spec.ts index a2330025c92..fec972c82f2 100644 --- a/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.spec.ts +++ b/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.spec.ts @@ -57,6 +57,7 @@ import { KeyRotationTrustInfoComponent, } from "@bitwarden/key-management-ui"; import { BitwardenClient, PureCrypto } from "@bitwarden/sdk-internal"; +import { UserKeyRotationServiceAbstraction } from "@bitwarden/user-crypto-management"; import { OrganizationUserResetPasswordService } from "../../admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service"; import { WebauthnLoginAdminService } from "../../auth"; @@ -287,6 +288,7 @@ describe("KeyRotationService", () => { let mockSdkClientFactory: MockProxy; let mockSecurityStateService: MockProxy; let mockMasterPasswordService: MockProxy; + let mockSdkUserKeyRotationService: MockProxy; const mockUser = { id: "mockUserId" as UserId, @@ -348,6 +350,7 @@ describe("KeyRotationService", () => { mockDialogService = mock(); mockCryptoFunctionService = mock(); mockKdfConfigService = mock(); + mockSdkUserKeyRotationService = mock(); mockSdkClientFactory = mock(); mockSdkClientFactory.createSdkClient.mockResolvedValue({ crypto: () => { @@ -358,6 +361,7 @@ describe("KeyRotationService", () => { } as any; }, } as BitwardenClient); + mockSecurityStateService = mock(); mockMasterPasswordService = mock(); @@ -384,6 +388,7 @@ describe("KeyRotationService", () => { mockSdkClientFactory, mockSecurityStateService, mockMasterPasswordService, + mockSdkUserKeyRotationService, ); }); @@ -509,7 +514,12 @@ describe("KeyRotationService", () => { ); mockKeyService.userSigningKey$.mockReturnValue(new BehaviorSubject(null)); mockSecurityStateService.accountSecurityState$.mockReturnValue(new BehaviorSubject(null)); - mockConfigService.getFeatureFlag.mockResolvedValue(true); + mockConfigService.getFeatureFlag.mockImplementation(async (flag: FeatureFlag) => { + if (flag === FeatureFlag.EnrollAeadOnKeyRotation) { + return true; + } + return false; + }); const spy = jest.spyOn(keyRotationService, "getRotatedAccountKeysFlagged").mockResolvedValue({ userKey: TEST_VECTOR_USER_KEY_V2, diff --git a/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.ts b/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.ts index 4102f3e5554..26dcacd8f11 100644 --- a/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.ts +++ b/apps/web/src/app/key-management/key-rotation/user-key-rotation.service.ts @@ -22,7 +22,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; -import { asUuid, SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; +import { asUuid } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; import { EncryptionType, HashPurpose } from "@bitwarden/common/platform/enums"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; @@ -39,10 +39,7 @@ import { KeyRotationTrustInfoComponent, } from "@bitwarden/key-management-ui"; import { PureCrypto, TokenProvider } from "@bitwarden/sdk-internal"; -import { - UserKeyRotationService as SdkUserKeyRotationService, - UserKeyRotationServiceAbstraction, -} from "@bitwarden/user-crypto-management"; +import { UserKeyRotationServiceAbstraction } from "@bitwarden/user-crypto-management"; import { OrganizationUserResetPasswordService } from "../../admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service"; import { WebauthnLoginAdminService } from "../../auth/core"; @@ -71,7 +68,7 @@ type MasterPasswordAuthenticationAndUnlockData = { * A token provider that exposes a null access token to the SDK. */ class NoopTokenProvider implements TokenProvider { - constructor() { } + constructor() {} async get_access_token(): Promise { // Ignore from the test coverage, since this is called by the SDK @@ -104,9 +101,9 @@ export class UserKeyRotationService { private kdfConfigService: KdfConfigService, private sdkClientFactory: SdkClientFactory, private securityStateService: SecurityStateService, - private sdkService: SdkService, private masterPasswordService: MasterPasswordServiceAbstraction, - ) { } + private sdkUserKeyRotationService: UserKeyRotationServiceAbstraction, + ) {} /** * Creates a new user key and re-encrypts all required data with the it. @@ -126,13 +123,11 @@ export class UserKeyRotationService { this.logService.info( "[UserKey Rotation] Using SDK-based key rotation service from user-crypto-management", ); - const sdkUserKeyRotationService: UserKeyRotationServiceAbstraction = - new SdkUserKeyRotationService(this.sdkService, this.logService, this.dialogService); - await sdkUserKeyRotationService.changePasswordAndRotateUserKey( + await this.sdkUserKeyRotationService.changePasswordAndRotateUserKey( currentMasterPassword, newMasterPassword, newMasterPasswordHint, - user.id, + asUuid(user.id), ); this.toastService.showToast({ variant: "success", diff --git a/libs/user-crypto-management/src/user-key-rotation.service.abstraction.ts b/libs/user-crypto-management/src/user-key-rotation.service.abstraction.ts index b7780b18d5d..796af456526 100644 --- a/libs/user-crypto-management/src/user-key-rotation.service.abstraction.ts +++ b/libs/user-crypto-management/src/user-key-rotation.service.abstraction.ts @@ -1,4 +1,5 @@ -import { PublicKey, UserId } from "@bitwarden/sdk-internal"; +import { PublicKey } from "@bitwarden/sdk-internal"; +import { UserId } from "@bitwarden/user-core"; /** * Result of the trust verification process. diff --git a/libs/user-crypto-management/src/user-key-rotation.service.ts b/libs/user-crypto-management/src/user-key-rotation.service.ts index beaace21c15..a1af0f7f80e 100644 --- a/libs/user-crypto-management/src/user-key-rotation.service.ts +++ b/libs/user-crypto-management/src/user-key-rotation.service.ts @@ -1,6 +1,7 @@ import { catchError, EMPTY, firstValueFrom, map } from "rxjs"; import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; import { DialogService } from "@bitwarden/components"; import { AccountRecoveryTrustComponent, @@ -85,7 +86,7 @@ export class DefaultUserKeyRotationService implements UserKeyRotationService { // 2. Show the user a dialog for each organization and ask them to verify the trust. // 3. Show the user a dialog for each emergency access user and ask them to verify the trust. this.logService.info("[Userkey rotation] Verifying trust..."); - const [emergencyAccessMemberships, organizationV1Memberships] = await firstValueFrom( + const [emergencyAccessV1Memberships, organizationV1Memberships] = await firstValueFrom( this.sdkService.userClient$(userId).pipe( map(async (sdk) => { if (!sdk) { @@ -93,22 +94,22 @@ export class DefaultUserKeyRotationService implements UserKeyRotationService { } using ref = sdk.take(); - const emergencyAccessMemberships = await ref.value + const emergencyAccessV1Memberships = await ref.value .user_crypto_management() .get_untrusted_emergency_access_public_keys(); const organizationV1Memberships = await ref.value .user_crypto_management() .get_untrusted_organization_public_keys(); - return [emergencyAccessMemberships, organizationV1Memberships] as const; + return [emergencyAccessV1Memberships, organizationV1Memberships] as const; }), ), ); - this.logService.info("result", { emergencyAccessMemberships, organizationV1Memberships }); + this.logService.info("result", { emergencyAccessV1Memberships, organizationV1Memberships }); - if (organizationV1Memberships.length > 0 || emergencyAccessMemberships.length > 0) { + if (organizationV1Memberships.length > 0 || emergencyAccessV1Memberships.length > 0) { this.logService.info("[Userkey rotation] Showing trust info dialog..."); const trustInfoDialog = KeyRotationTrustInfoComponent.open(this.dialogService, { - numberOfEmergencyAccessUsers: emergencyAccessMemberships.length, + numberOfEmergencyAccessUsers: emergencyAccessV1Memberships.length, orgName: organizationV1Memberships.length > 0 ? organizationV1Memberships[0].name : undefined, }); @@ -125,7 +126,7 @@ export class DefaultUserKeyRotationService implements UserKeyRotationService { const dialogRef = AccountRecoveryTrustComponent.open(this.dialogService, { name: organization.name, orgId: organization.organization_id as string, - publicKey: organization.public_key, + publicKey: Utils.fromB64ToArray(organization.public_key), }); if (!(await firstValueFrom(dialogRef.closed))) { return { @@ -136,11 +137,11 @@ export class DefaultUserKeyRotationService implements UserKeyRotationService { } } - for (const details of emergencyAccessMemberships) { + for (const details of emergencyAccessV1Memberships) { const dialogRef = EmergencyAccessTrustComponent.open(this.dialogService, { name: details.name, userId: details.id as string, - publicKey: details.public_key, + publicKey: Utils.fromB64ToArray(details.public_key), }); if (!(await firstValueFrom(dialogRef.closed))) { return { @@ -157,7 +158,7 @@ export class DefaultUserKeyRotationService implements UserKeyRotationService { return { wasTrustDenied: false, trustedOrganizationPublicKeys: organizationV1Memberships.map((d) => d.public_key), - trustedEmergencyAccessUserPublicKeys: emergencyAccessMemberships.map((d) => d.public_key), + trustedEmergencyAccessUserPublicKeys: emergencyAccessV1Memberships.map((d) => d.public_key), }; } }