From 034f16f29e29ea59f7955d60567e0ba63ca4c4cf Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Wed, 5 Apr 2023 16:43:13 +0200 Subject: [PATCH] [EC-598] feat: add rudimentary support for excluded credentials --- .../browser-fido2-user-interface.service.ts | 19 +++++++++++++------ .../webauthn/popup/fido2/fido2.component.html | 12 ++++++++++++ .../webauthn/popup/fido2/fido2.component.ts | 7 +++++++ ...ido2-user-interface.service.abstraction.ts | 1 - .../services/fido2-authenticator.service.ts | 7 ++----- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts index 6a348fef40..47bf8aa8b7 100644 --- a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts +++ b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts @@ -75,6 +75,10 @@ export type BrowserFido2Message = { sessionId: string } & ( type: "ConfirmNewNonDiscoverableCredentialResponse"; cipherId: string; } + | { + type: "InformExcludedCredentialRequest"; + existingCipherIds: string[]; + } | { type: "AbortRequest"; } @@ -222,12 +226,15 @@ export class BrowserFido2UserInterfaceSession implements Fido2UserInterfaceSessi return response.cipherId; } - informExcludedCredential( - existingCipherIds: string[], - newCredential: NewCredentialParams, - abortController?: AbortController - ): Promise { - return null; + async informExcludedCredential(existingCipherIds: string[]): Promise { + const data: BrowserFido2Message = { + type: "InformExcludedCredentialRequest", + sessionId: this.sessionId, + existingCipherIds, + }; + + await this.send(data); + await this.receive("AbortResponse"); } private async send(msg: BrowserFido2Message): Promise { diff --git a/apps/browser/src/webauthn/popup/fido2/fido2.component.html b/apps/browser/src/webauthn/popup/fido2/fido2.component.html index 07670e7134..53ce8d1b45 100644 --- a/apps/browser/src/webauthn/popup/fido2/fido2.component.html +++ b/apps/browser/src/webauthn/popup/fido2/fido2.component.html @@ -37,6 +37,18 @@ + + A passkey already exists in Bitwarden for this account +
+
+ +
+
+
diff --git a/apps/browser/src/webauthn/popup/fido2/fido2.component.ts b/apps/browser/src/webauthn/popup/fido2/fido2.component.ts index 191002c44a..665ad613f3 100644 --- a/apps/browser/src/webauthn/popup/fido2/fido2.component.ts +++ b/apps/browser/src/webauthn/popup/fido2/fido2.component.ts @@ -85,6 +85,13 @@ export class Fido2Component implements OnInit, OnDestroy { this.ciphers = (await this.cipherService.getAllDecrypted()).filter( (cipher) => cipher.type === CipherType.Login && !cipher.isDeleted ); + } else if (data?.type === "InformExcludedCredentialRequest") { + this.ciphers = await Promise.all( + data.existingCipherIds.map(async (cipherId) => { + const cipher = await this.cipherService.get(cipherId); + return cipher.decrypt(); + }) + ); } }), takeUntil(this.destroy$) diff --git a/libs/common/src/webauthn/abstractions/fido2-user-interface.service.abstraction.ts b/libs/common/src/webauthn/abstractions/fido2-user-interface.service.abstraction.ts index 8313ec5102..81fe02755e 100644 --- a/libs/common/src/webauthn/abstractions/fido2-user-interface.service.abstraction.ts +++ b/libs/common/src/webauthn/abstractions/fido2-user-interface.service.abstraction.ts @@ -39,7 +39,6 @@ export abstract class Fido2UserInterfaceSession { ) => Promise; informExcludedCredential: ( existingCipherIds: string[], - newCredential: NewCredentialParams, abortController?: AbortController ) => Promise; } diff --git a/libs/common/src/webauthn/services/fido2-authenticator.service.ts b/libs/common/src/webauthn/services/fido2-authenticator.service.ts index daea9a440e..055f2b7fa8 100644 --- a/libs/common/src/webauthn/services/fido2-authenticator.service.ts +++ b/libs/common/src/webauthn/services/fido2-authenticator.service.ts @@ -65,11 +65,8 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr const isExcluded = await this.vaultContainsCredentials(params.excludeCredentialDescriptorList); if (isExcluded) { await userInterfaceSession.informExcludedCredential( - [Utils.guidToStandardFormat(params.excludeCredentialDescriptorList[0].id)], - { - credentialName: params.rpEntity.name, - userName: params.userEntity.displayName, - }, + // [Utils.guidToStandardFormat(params.excludeCredentialDescriptorList[0].id)], + [], abortController );