diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts index 6cc94ef2d11..1c7d870175d 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.spec.ts @@ -117,14 +117,7 @@ describe("EmergencyAccessService", () => { const granteeId = "grantee-id"; const mockUserKey = new SymmetricCryptoKey(new Uint8Array(64)) as UserKey; - const mockPublicKeyB64 = "some-public-key-in-base64"; - - // const publicKey = Utils.fromB64ToArray(publicKeyB64); - - const mockUserPublicKeyResponse = new UserKeyResponse({ - UserId: granteeId, - PublicKey: mockPublicKeyB64, - }); + const publicKey = new Uint8Array(64); const mockUserPublicKeyEncryptedUserKey = new EncString( EncryptionType.AesCbc256_HmacSha256_B64, @@ -132,14 +125,13 @@ describe("EmergencyAccessService", () => { ); keyService.getUserKey.mockResolvedValueOnce(mockUserKey); - apiService.getUserPublicKey.mockResolvedValueOnce(mockUserPublicKeyResponse); encryptService.rsaEncrypt.mockResolvedValueOnce(mockUserPublicKeyEncryptedUserKey); emergencyAccessApiService.postEmergencyAccessConfirm.mockResolvedValueOnce(); // Act - await emergencyAccessService.confirm(id, granteeId); + await emergencyAccessService.confirm(id, granteeId, publicKey); // Assert expect(emergencyAccessApiService.postEmergencyAccessConfirm).toHaveBeenCalledWith(id, { diff --git a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts index acdf7623f9b..62a59da2995 100644 --- a/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts +++ b/apps/web/src/app/auth/emergency-access/services/emergency-access.service.ts @@ -153,14 +153,13 @@ export class EmergencyAccessService * Intended for grantor. * @param id emergency access id * @param token secret token provided in email + * @param publicKey public key of grantee */ - async confirm(id: string, granteeId: string) { + async confirm(id: string, granteeId: string, publicKey: Uint8Array): Promise { const userKey = await this.keyService.getUserKey(); if (!userKey) { throw new Error("No user key found"); } - const publicKeyResponse = await this.apiService.getUserPublicKey(granteeId); - const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); try { this.logService.debug( diff --git a/apps/web/src/app/auth/settings/emergency-access/confirm/emergency-access-confirm.component.ts b/apps/web/src/app/auth/settings/emergency-access/confirm/emergency-access-confirm.component.ts index 9c6296c22a9..1180c1a3542 100644 --- a/apps/web/src/app/auth/settings/emergency-access/confirm/emergency-access-confirm.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/confirm/emergency-access-confirm.component.ts @@ -4,10 +4,8 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, OnInit, Inject } from "@angular/core"; import { FormBuilder } from "@angular/forms"; -import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; -import { Utils } from "@bitwarden/common/platform/misc/utils"; import { DialogService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; @@ -21,6 +19,8 @@ type EmergencyAccessConfirmDialogData = { userId: string; /** traces a unique emergency request */ emergencyAccessId: string; + /** user public key */ + publicKey: Uint8Array; }; @Component({ selector: "emergency-access-confirm", @@ -36,7 +36,6 @@ export class EmergencyAccessConfirmComponent implements OnInit { constructor( @Inject(DIALOG_DATA) protected params: EmergencyAccessConfirmDialogData, private formBuilder: FormBuilder, - private apiService: ApiService, private keyService: KeyService, protected organizationManagementPreferencesService: OrganizationManagementPreferencesService, private logService: LogService, @@ -45,13 +44,12 @@ export class EmergencyAccessConfirmComponent implements OnInit { async ngOnInit() { try { - const publicKeyResponse = await this.apiService.getUserPublicKey(this.params.userId); - if (publicKeyResponse != null) { - const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); - const fingerprint = await this.keyService.getFingerprint(this.params.userId, publicKey); - if (fingerprint != null) { - this.fingerprint = fingerprint.join("-"); - } + const fingerprint = await this.keyService.getFingerprint( + this.params.userId, + this.params.publicKey, + ); + if (fingerprint != null) { + this.fingerprint = fingerprint.join("-"); } } catch (e) { this.logService.error(e); diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts index 5271e50c9a3..73e32add5c2 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access.component.ts @@ -4,6 +4,7 @@ import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core"; import { lastValueFrom, Observable, firstValueFrom, switchMap } from "rxjs"; import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; +import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; @@ -13,6 +14,7 @@ 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 { Utils } from "@bitwarden/common/platform/misc/utils"; import { DialogService, ToastService } from "@bitwarden/components"; import { EmergencyAccessService } from "../../emergency-access"; @@ -70,6 +72,7 @@ export class EmergencyAccessComponent implements OnInit { billingAccountProfileStateService: BillingAccountProfileStateService, protected organizationManagementPreferencesService: OrganizationManagementPreferencesService, private toastService: ToastService, + private apiService: ApiService, private accountService: AccountService, ) { this.canAccessPremium$ = this.accountService.activeAccount$.pipe( @@ -147,6 +150,9 @@ export class EmergencyAccessComponent implements OnInit { return; } + const publicKeyResponse = await this.apiService.getUserPublicKey(contact.granteeId); + const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); + const autoConfirm = await firstValueFrom( this.organizationManagementPreferencesService.autoConfirmFingerPrints.state$, ); @@ -156,11 +162,12 @@ export class EmergencyAccessComponent implements OnInit { name: this.userNamePipe.transform(contact), emergencyAccessId: contact.id, userId: contact?.granteeId, + publicKey, }, }); const result = await lastValueFrom(dialogRef.closed); if (result === EmergencyAccessConfirmDialogResult.Confirmed) { - await this.emergencyAccessService.confirm(contact.id, contact.granteeId); + await this.emergencyAccessService.confirm(contact.id, contact.granteeId, publicKey); updateUser(); this.toastService.showToast({ variant: "success", @@ -171,7 +178,11 @@ export class EmergencyAccessComponent implements OnInit { return; } - this.actionPromise = this.emergencyAccessService.confirm(contact.id, contact.granteeId); + this.actionPromise = this.emergencyAccessService.confirm( + contact.id, + contact.granteeId, + publicKey, + ); await this.actionPromise; updateUser();