From 7630ce881cde667afa3d0729801af8b92081bce0 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Fri, 16 Dec 2022 15:01:49 +0100 Subject: [PATCH] [EC-598] feat: rudimentar error handling --- .../src/background/runtime.background.ts | 12 ++++++++++-- .../src/content/webauthn/content-script.ts | 7 ++++--- .../src/content/webauthn/messaging/error.ts | 10 ++++++++++ .../src/content/webauthn/messaging/message.ts | 5 ++++- .../src/content/webauthn/page-script.ts | 18 +++++++++++++++++- .../src/popup/fido2/fido2.component.html | 5 ++++- .../browser/src/popup/fido2/fido2.component.ts | 8 +++++--- .../browser-fido2-user-interface.service.ts | 10 ++++++++++ .../fido2/fido2.service.abstraction.ts | 6 ++++++ 9 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 apps/browser/src/content/webauthn/messaging/error.ts diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index cbc73a8d70d..cbe3fec016b 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -209,9 +209,17 @@ export default class RuntimeBackground { this.platformUtilsService.copyToClipboard(msg.identifier, { window: window }); break; case "fido2RegisterCredentialRequest": - return await this.main.fido2Service.createCredential(msg.data); + try { + return { result: await this.main.fido2Service.createCredential(msg.data) }; + } catch (error) { + return { error: { ...error, message: error.message } }; + } case "fido2GetCredentialRequest": - return await this.main.fido2Service.assertCredential(msg.data); + try { + return { result: await this.main.fido2Service.assertCredential(msg.data) }; + } catch (error) { + return { error: { ...error, message: error.message } }; + } } return undefined; } diff --git a/apps/browser/src/content/webauthn/content-script.ts b/apps/browser/src/content/webauthn/content-script.ts index 6e3c04f1b54..51b32a29314 100644 --- a/apps/browser/src/content/webauthn/content-script.ts +++ b/apps/browser/src/content/webauthn/content-script.ts @@ -21,8 +21,8 @@ messenger.addHandler(async (message) => { (response) => { resolve({ type: MessageType.CredentialCreationResponse, - approved: true, - result: response, + result: response.result, + error: response.error, }); } ); @@ -39,7 +39,8 @@ messenger.addHandler(async (message) => { (response) => { resolve({ type: MessageType.CredentialGetResponse, - result: response, + result: response.result, + error: response.error, }); } ); diff --git a/apps/browser/src/content/webauthn/messaging/error.ts b/apps/browser/src/content/webauthn/messaging/error.ts new file mode 100644 index 00000000000..1513777f3c1 --- /dev/null +++ b/apps/browser/src/content/webauthn/messaging/error.ts @@ -0,0 +1,10 @@ +export enum MessageErrorType { + RequestAborted, +} + +export type RequestAbortedMessageError = { + fallbackRequested: boolean; + message: string; +}; + +export type MessageError = RequestAbortedMessageError; diff --git a/apps/browser/src/content/webauthn/messaging/message.ts b/apps/browser/src/content/webauthn/messaging/message.ts index 06d0c296749..ffde8346786 100644 --- a/apps/browser/src/content/webauthn/messaging/message.ts +++ b/apps/browser/src/content/webauthn/messaging/message.ts @@ -5,6 +5,8 @@ import { CredentialRegistrationResult, } from "@bitwarden/common/abstractions/fido2/fido2.service.abstraction"; +import { MessageError } from "./error"; + export enum MessageType { CredentialCreationRequest, CredentialCreationResponse, @@ -21,8 +23,8 @@ export type CredentialCreationRequest = { export type CredentialCreationResponse = { type: MessageType.CredentialCreationResponse; - approved: boolean; result?: CredentialRegistrationResult; + error?: MessageError; }; export type CredentialGetRequest = { @@ -33,6 +35,7 @@ export type CredentialGetRequest = { export type CredentialGetResponse = { type: MessageType.CredentialGetResponse; result?: CredentialAssertResult; + error?: MessageError; }; export type AbortRequest = { diff --git a/apps/browser/src/content/webauthn/page-script.ts b/apps/browser/src/content/webauthn/page-script.ts index b5438cdfc81..bc214784069 100644 --- a/apps/browser/src/content/webauthn/page-script.ts +++ b/apps/browser/src/content/webauthn/page-script.ts @@ -19,10 +19,18 @@ navigator.credentials.create = async (options?: CredentialCreationOptions): Prom data: WebauthnUtils.mapCredentialCreationOptions(options, window.location.origin), }); - if (response.type !== MessageType.CredentialCreationResponse || !response.approved) { + if (response.type !== MessageType.CredentialCreationResponse) { return await browserCredentials.create(options); } + if (response.error && response.error.fallbackRequested) { + return await browserCredentials.create(options); + } + + if (response.error) { + throw new Error(response.error.message ?? "The request was aborted."); + } + return WebauthnUtils.mapCredentialRegistrationResult(response.result); }; @@ -36,5 +44,13 @@ navigator.credentials.get = async (options?: CredentialRequestOptions): Promise< return await browserCredentials.get(options); } + if (response.error && response.error.fallbackRequested) { + return await browserCredentials.create(options); + } + + if (response.error) { + throw new Error(response.error.message ?? "The request was aborted."); + } + return WebauthnUtils.mapCredentialAssertResult(response.result); }; diff --git a/apps/browser/src/popup/fido2/fido2.component.html b/apps/browser/src/popup/fido2/fido2.component.html index b7c0068b2df..efed0eb967d 100644 --- a/apps/browser/src/popup/fido2/fido2.component.html +++ b/apps/browser/src/popup/fido2/fido2.component.html @@ -9,5 +9,8 @@ Authenticate Create - + + diff --git a/apps/browser/src/popup/fido2/fido2.component.ts b/apps/browser/src/popup/fido2/fido2.component.ts index d59806fed9c..7695001dbad 100644 --- a/apps/browser/src/popup/fido2/fido2.component.ts +++ b/apps/browser/src/popup/fido2/fido2.component.ts @@ -35,23 +35,25 @@ export class Fido2Component { BrowserFido2UserInterfaceService.sendMessage({ requestId: data.requestId, type: "RequestCancelled", + fallbackRequested: true, }); } window.close(); } - cancel() { - this.unload(); + cancel(fallback: boolean) { + this.unload(fallback); window.close(); } @HostListener("window:unload") - unload() { + unload(fallback = true) { const data = this.data; BrowserFido2UserInterfaceService.sendMessage({ requestId: data.requestId, type: "RequestCancelled", + fallbackRequested: fallback, }); } } 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 cf4c1d70278..e8f18923f52 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 @@ -3,6 +3,7 @@ import { filter, first, lastValueFrom, Subject, takeUntil } from "rxjs"; import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction"; import { Utils } from "@bitwarden/common/misc/utils"; +import { RequestAbortedError } from "../../../../../libs/common/src/abstractions/fido2/fido2.service.abstraction"; import { BrowserApi } from "../../browser/browserApi"; import { PopupUtilsService } from "../../popup/services/popup-utils.service"; @@ -23,6 +24,7 @@ export type BrowserFido2Message = { requestId: string } & ( } | { type: "RequestCancelled"; + fallbackRequested: boolean; } ); @@ -68,6 +70,10 @@ export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServi return true; } + if (response.type === "RequestCancelled") { + throw new RequestAbortedError(response.fallbackRequested); + } + return false; } @@ -93,6 +99,10 @@ export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServi return true; } + if (response.type === "RequestCancelled") { + throw new RequestAbortedError(response.fallbackRequested); + } + return false; } diff --git a/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts b/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts index 9466cb6cb27..1e9d9d382e7 100644 --- a/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts +++ b/libs/common/src/abstractions/fido2/fido2.service.abstraction.ts @@ -54,6 +54,12 @@ export interface CredentialAssertResult { userHandle: string; } +export class RequestAbortedError extends Error { + constructor(readonly fallbackRequested = false) { + super("Fido2 request was aborted"); + } +} + export abstract class Fido2Service { createCredential: (params: CredentialRegistrationParams) => Promise; assertCredential: (params: CredentialAssertParams) => Promise;