From 75e07cfbedab2ceb80ef7f39486e7aed5ef7975c Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 28 Sep 2023 23:49:55 -0700 Subject: Add new method to manually cancel active ceremony --- .../src/helpers/webAuthnAbortService.test.ts | 23 ++++++++++++++++++++++ .../browser/src/helpers/webAuthnAbortService.ts | 15 ++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'packages/browser/src') diff --git a/packages/browser/src/helpers/webAuthnAbortService.test.ts b/packages/browser/src/helpers/webAuthnAbortService.test.ts index a538dff..fd2ca7a 100644 --- a/packages/browser/src/helpers/webAuthnAbortService.test.ts +++ b/packages/browser/src/helpers/webAuthnAbortService.test.ts @@ -25,3 +25,26 @@ test('should call abort() with AbortError on existing controller when creating a expect(abortReason).toBeInstanceOf(Error); expect(abortReason.name).toEqual('AbortError'); }); + +test('should cancel active WebAuthn ceremony when manually cancelled', () => { + // Populate `.controller` + WebauthnAbortService.createNewAbortSignal(); + + // Spy on the existing instance of AbortController + const abortSpy = jest.fn(); + // @ts-ignore: Ignore the fact that `controller` is private + WebauthnAbortService.controller.abort = abortSpy; + + // Cancel the in-flight ceremony, which should call `abort()` on the existing controller + WebauthnAbortService.cancelCeremony(); + expect(abortSpy).toHaveBeenCalledTimes(1); + + // Make sure we raise an AbortError so it can be detected correctly + const abortReason = abortSpy.mock.calls[0][0]; + expect(abortReason).toBeInstanceOf(Error); + expect(abortReason.name).toEqual('AbortError'); + + // Ensure that we don't set up a new AbortController because it's unnecessary to do so + // @ts-ignore: Ignore the fact that `controller` is private + expect(WebauthnAbortService.controller).toBeUndefined(); +}); diff --git a/packages/browser/src/helpers/webAuthnAbortService.ts b/packages/browser/src/helpers/webAuthnAbortService.ts index ce6979c..da5380b 100644 --- a/packages/browser/src/helpers/webAuthnAbortService.ts +++ b/packages/browser/src/helpers/webAuthnAbortService.ts @@ -21,6 +21,21 @@ class BaseWebAuthnAbortService { this.controller = newController; return newController.signal; } + + /** + * Manually cancel any active WebAuthn registration or authentication attempt. + */ + cancelCeremony() { + if (this.controller) { + const abortError = new Error( + 'Manually cancelling existing WebAuthn API call', + ); + abortError.name = 'AbortError'; + this.controller.abort(abortError); + + this.controller = undefined; + } + } } /** -- cgit v1.2.3