diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 89d335a40ac..beef1b7246b 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -535,6 +535,7 @@ export default class MainBackground { this.fido2AuthenticatorService = new Fido2AuthenticatorService( this.cipherService, this.fido2UserInterfaceService, + this.syncService, this.logService ); this.fido2ClientService = new Fido2ClientService( diff --git a/apps/browser/src/platform/browser/browser-api.ts b/apps/browser/src/platform/browser/browser-api.ts index ca0b08a3518..10238b283cb 100644 --- a/apps/browser/src/platform/browser/browser-api.ts +++ b/apps/browser/src/platform/browser/browser-api.ts @@ -1,4 +1,4 @@ -import { NgZone } from "@angular/core"; +import type { NgZone } from "@angular/core"; import { Observable } from "rxjs"; import { DeviceType } from "@bitwarden/common/enums"; @@ -213,7 +213,15 @@ export class BrowserApi { } } - //Ngzone run is added to fix the issue on Fido2Component, where the message listener is not running in the angular zone + /** + * Creates an observable that listens for messages. If an Angular zone is provided, + * ensures that the message processing runs within that zone, triggering change detection. + * This solution was devised to address an issue in the `Fido2Component`, where the + * original message listener operated outside the Angular zone. + * + * @param {NgZone} [zone] - An optional Angular zone to ensure UI updates and change + * detection are triggered. If omitted, operates outside the Angular zone. + */ static messageListener$(zone?: NgZone) { return new Observable((subscriber) => { const handler = (message: unknown) => { diff --git a/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts b/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts index 92898df9522..82a65f2a0fe 100644 --- a/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts +++ b/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts @@ -15,6 +15,7 @@ import { Fido2UserInterfaceSession, NewCredentialParams, } from "../../abstractions/fido2/fido2-user-interface.service.abstraction"; +import { SyncService } from "../../abstractions/sync/sync.service.abstraction"; import { CipherType } from "../../enums/cipher-type"; import { Cipher } from "../../models/domain/cipher"; import { CipherView } from "../../models/view/cipher.view"; @@ -30,6 +31,7 @@ describe("FidoAuthenticatorService", () => { let cipherService!: MockProxy; let userInterface!: MockProxy; let userInterfaceSession!: MockProxy; + let syncService!: MockProxy; let authenticator!: Fido2AuthenticatorService; beforeEach(async () => { @@ -37,7 +39,8 @@ describe("FidoAuthenticatorService", () => { userInterface = mock(); userInterfaceSession = mock(); userInterface.newSession.mockResolvedValue(userInterfaceSession); - authenticator = new Fido2AuthenticatorService(cipherService, userInterface); + syncService = mock(); + authenticator = new Fido2AuthenticatorService(cipherService, userInterface, syncService); }); describe("makeCredential", () => { diff --git a/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts b/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts index 843bd034e47..251144e8ce7 100644 --- a/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts +++ b/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts @@ -15,6 +15,7 @@ import { PublicKeyCredentialDescriptor, } from "../../abstractions/fido2/fido2-authenticator.service.abstraction"; import { Fido2UserInterfaceService } from "../../abstractions/fido2/fido2-user-interface.service.abstraction"; +import { SyncService } from "../../abstractions/sync/sync.service.abstraction"; import { CipherType } from "../../enums/cipher-type"; import { CipherView } from "../../models/view/cipher.view"; import { Fido2KeyView } from "../../models/view/fido2-key.view"; @@ -37,6 +38,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr constructor( private cipherService: CipherService, private userInterface: Fido2UserInterfaceService, + private syncService: SyncService, private logService?: LogService ) {} async makeCredential( @@ -81,6 +83,9 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr throw new Fido2AutenticatorError(Fido2AutenticatorErrorCode.Unknown); } + //TODO: uncomment this when working on the login flow ticket + // await userInterfaceSession.ensureUnlockedVault(); + const existingCipherIds = await this.findExcludedCredentials( params.excludeCredentialDescriptorList ); @@ -376,6 +381,11 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr return []; } + //ensure full sync has completed before getting the ciphers + if ((await this.syncService.getLastSync()) == null) { + await this.syncService.fullSync(false); + } + const ciphers = await this.cipherService.getAllDecrypted(); return ciphers.filter( (cipher) => @@ -391,6 +401,11 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr } private async findCredentialsByRp(rpId: string): Promise { + //ensure full sync has completed before getting the ciphers + if ((await this.syncService.getLastSync()) == null) { + await this.syncService.fullSync(false); + } + const ciphers = await this.cipherService.getAllDecrypted(); return ciphers.filter( (cipher) =>