From d2777819d7904945b817ca46447853d32803a219 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 28 Sep 2023 23:48:54 -0700 Subject: Rename webauthnAbortService --- packages/browser/src/helpers/webAuthnAbortService.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/browser/src/helpers/webAuthnAbortService.test.ts') diff --git a/packages/browser/src/helpers/webAuthnAbortService.test.ts b/packages/browser/src/helpers/webAuthnAbortService.test.ts index 506bb2a..a538dff 100644 --- a/packages/browser/src/helpers/webAuthnAbortService.test.ts +++ b/packages/browser/src/helpers/webAuthnAbortService.test.ts @@ -1,23 +1,23 @@ -import { webauthnAbortService } from './webAuthnAbortService'; +import { WebauthnAbortService } from './webAuthnAbortService'; test('should create a new abort signal every time', () => { - const signal1 = webauthnAbortService.createNewAbortSignal(); - const signal2 = webauthnAbortService.createNewAbortSignal(); + const signal1 = WebauthnAbortService.createNewAbortSignal(); + const signal2 = WebauthnAbortService.createNewAbortSignal(); expect(signal2).not.toBe(signal1); }); test('should call abort() with AbortError on existing controller when creating a new signal', () => { // Populate `.controller` - webauthnAbortService.createNewAbortSignal(); + 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; + WebauthnAbortService.controller.abort = abortSpy; // Generate a new signal, which should call `abort()` on the existing controller - webauthnAbortService.createNewAbortSignal(); + WebauthnAbortService.createNewAbortSignal(); expect(abortSpy).toHaveBeenCalledTimes(1); // Make sure we raise an AbortError so it can be detected correctly -- cgit v1.2.3 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/helpers/webAuthnAbortService.test.ts') 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 From 113ae8eeb635b36b4ce0be464837d99af7ba1382 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 28 Sep 2023 23:54:21 -0700 Subject: Fix capitalization issue --- .../browser/src/helpers/webAuthnAbortService.test.ts | 20 ++++++++++---------- packages/browser/src/helpers/webAuthnAbortService.ts | 2 +- packages/browser/src/index.ts | 4 ++-- .../browser/src/methods/startAuthentication.test.ts | 4 ++-- packages/browser/src/methods/startAuthentication.ts | 4 ++-- .../browser/src/methods/startRegistration.test.ts | 4 ++-- packages/browser/src/methods/startRegistration.ts | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) (limited to 'packages/browser/src/helpers/webAuthnAbortService.test.ts') diff --git a/packages/browser/src/helpers/webAuthnAbortService.test.ts b/packages/browser/src/helpers/webAuthnAbortService.test.ts index fd2ca7a..87d2535 100644 --- a/packages/browser/src/helpers/webAuthnAbortService.test.ts +++ b/packages/browser/src/helpers/webAuthnAbortService.test.ts @@ -1,23 +1,23 @@ -import { WebauthnAbortService } from './webAuthnAbortService'; +import { WebAuthnAbortService } from './webAuthnAbortService'; test('should create a new abort signal every time', () => { - const signal1 = WebauthnAbortService.createNewAbortSignal(); - const signal2 = WebauthnAbortService.createNewAbortSignal(); + const signal1 = WebAuthnAbortService.createNewAbortSignal(); + const signal2 = WebAuthnAbortService.createNewAbortSignal(); expect(signal2).not.toBe(signal1); }); test('should call abort() with AbortError on existing controller when creating a new signal', () => { // Populate `.controller` - WebauthnAbortService.createNewAbortSignal(); + 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; + WebAuthnAbortService.controller.abort = abortSpy; // Generate a new signal, which should call `abort()` on the existing controller - WebauthnAbortService.createNewAbortSignal(); + WebAuthnAbortService.createNewAbortSignal(); expect(abortSpy).toHaveBeenCalledTimes(1); // Make sure we raise an AbortError so it can be detected correctly @@ -28,15 +28,15 @@ test('should call abort() with AbortError on existing controller when creating a test('should cancel active WebAuthn ceremony when manually cancelled', () => { // Populate `.controller` - WebauthnAbortService.createNewAbortSignal(); + 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; + WebAuthnAbortService.controller.abort = abortSpy; // Cancel the in-flight ceremony, which should call `abort()` on the existing controller - WebauthnAbortService.cancelCeremony(); + WebAuthnAbortService.cancelCeremony(); expect(abortSpy).toHaveBeenCalledTimes(1); // Make sure we raise an AbortError so it can be detected correctly @@ -46,5 +46,5 @@ test('should cancel active WebAuthn ceremony when manually cancelled', () => { // 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(); + expect(WebAuthnAbortService.controller).toBeUndefined(); }); diff --git a/packages/browser/src/helpers/webAuthnAbortService.ts b/packages/browser/src/helpers/webAuthnAbortService.ts index da5380b..395ceea 100644 --- a/packages/browser/src/helpers/webAuthnAbortService.ts +++ b/packages/browser/src/helpers/webAuthnAbortService.ts @@ -45,4 +45,4 @@ class BaseWebAuthnAbortService { * developers building projects that use client-side routing to better control the behavior of * their UX in response to router navigation events. */ -export const WebauthnAbortService = new BaseWebAuthnAbortService(); +export const WebAuthnAbortService = new BaseWebAuthnAbortService(); diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 9805fe6..d45fafb 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -9,7 +9,7 @@ import { platformAuthenticatorIsAvailable } from './helpers/platformAuthenticato import { browserSupportsWebAuthnAutofill } from './helpers/browserSupportsWebAuthnAutofill'; import { base64URLStringToBuffer } from './helpers/base64URLStringToBuffer'; import { bufferToBase64URLString } from './helpers/bufferToBase64URLString'; -import { WebauthnAbortService } from './helpers/webAuthnAbortService'; +import { WebAuthnAbortService } from './helpers/webAuthnAbortService'; export { base64URLStringToBuffer, @@ -19,7 +19,7 @@ export { platformAuthenticatorIsAvailable, startAuthentication, startRegistration, - WebauthnAbortService, + WebAuthnAbortService, }; export type { WebAuthnErrorCode } from './helpers/webAuthnError'; diff --git a/packages/browser/src/methods/startAuthentication.test.ts b/packages/browser/src/methods/startAuthentication.test.ts index e535202..fb31dcc 100644 --- a/packages/browser/src/methods/startAuthentication.test.ts +++ b/packages/browser/src/methods/startAuthentication.test.ts @@ -11,7 +11,7 @@ import { utf8StringToBuffer } from '../helpers/utf8StringToBuffer'; import { bufferToBase64URLString } from '../helpers/bufferToBase64URLString'; import { WebAuthnError } from '../helpers/webAuthnError'; import { generateCustomError } from '../helpers/__jest__/generateCustomError'; -import { WebauthnAbortService } from '../helpers/webAuthnAbortService'; +import { WebAuthnAbortService } from '../helpers/webAuthnAbortService'; import { startAuthentication } from './startAuthentication'; @@ -62,7 +62,7 @@ beforeEach(() => { mockSupportsAutofill.mockResolvedValue(true); // Reset the abort service so we get an accurate call count - WebauthnAbortService.cancelCeremony(); + WebAuthnAbortService.cancelCeremony(); }); afterEach(() => { diff --git a/packages/browser/src/methods/startAuthentication.ts b/packages/browser/src/methods/startAuthentication.ts index 8474878..6e3940d 100644 --- a/packages/browser/src/methods/startAuthentication.ts +++ b/packages/browser/src/methods/startAuthentication.ts @@ -11,7 +11,7 @@ import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn'; import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsWebAuthnAutofill'; import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor'; import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError'; -import { WebauthnAbortService } from '../helpers/webAuthnAbortService'; +import { WebAuthnAbortService } from '../helpers/webAuthnAbortService'; import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment'; /** @@ -79,7 +79,7 @@ export async function startAuthentication( // Finalize options options.publicKey = publicKey; // Set up the ability to cancel this request if the user attempts another - options.signal = WebauthnAbortService.createNewAbortSignal(); + options.signal = WebAuthnAbortService.createNewAbortSignal(); // Wait for the user to complete assertion let credential; diff --git a/packages/browser/src/methods/startRegistration.test.ts b/packages/browser/src/methods/startRegistration.test.ts index 66560b1..ee0b604 100644 --- a/packages/browser/src/methods/startRegistration.test.ts +++ b/packages/browser/src/methods/startRegistration.test.ts @@ -8,7 +8,7 @@ import { generateCustomError } from '../helpers/__jest__/generateCustomError'; import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn'; import { bufferToBase64URLString } from '../helpers/bufferToBase64URLString'; import { WebAuthnError } from '../helpers/webAuthnError'; -import { WebauthnAbortService } from '../helpers/webAuthnAbortService'; +import { WebAuthnAbortService } from '../helpers/webAuthnAbortService'; import { utf8StringToBuffer } from '../helpers/utf8StringToBuffer'; @@ -61,7 +61,7 @@ beforeEach(() => { mockSupportsWebauthn.mockReturnValue(true); // Reset the abort service so we get an accurate call count - WebauthnAbortService.cancelCeremony(); + WebAuthnAbortService.cancelCeremony(); }); afterEach(() => { diff --git a/packages/browser/src/methods/startRegistration.ts b/packages/browser/src/methods/startRegistration.ts index c34c21c..3ffa7d1 100644 --- a/packages/browser/src/methods/startRegistration.ts +++ b/packages/browser/src/methods/startRegistration.ts @@ -11,7 +11,7 @@ import { base64URLStringToBuffer } from '../helpers/base64URLStringToBuffer'; import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn'; import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor'; import { identifyRegistrationError } from '../helpers/identifyRegistrationError'; -import { WebauthnAbortService } from '../helpers/webAuthnAbortService'; +import { WebAuthnAbortService } from '../helpers/webAuthnAbortService'; import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment'; /** @@ -42,7 +42,7 @@ export async function startRegistration( // Finalize options const options: CredentialCreationOptions = { publicKey }; // Set up the ability to cancel this request if the user attempts another - options.signal = WebauthnAbortService.createNewAbortSignal(); + options.signal = WebAuthnAbortService.createNewAbortSignal(); // Wait for the user to complete attestation let credential; -- cgit v1.2.3