From 6b1f531754a2816bc4d0a0ea51543a1c6ba54316 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Fri, 17 Jun 2022 23:03:46 -0700 Subject: Create WebAuthnAbortService for abort signal mgmt --- .../browser/src/helpers/webAuthnAbortService.ts | 23 ++++++++++++++++++++++ .../browser/src/methods/startAuthentication.ts | 3 +++ packages/browser/src/methods/startRegistration.ts | 3 +++ 3 files changed, 29 insertions(+) create mode 100644 packages/browser/src/helpers/webAuthnAbortService.ts (limited to 'packages/browser/src') diff --git a/packages/browser/src/helpers/webAuthnAbortService.ts b/packages/browser/src/helpers/webAuthnAbortService.ts new file mode 100644 index 0000000..35e2f29 --- /dev/null +++ b/packages/browser/src/helpers/webAuthnAbortService.ts @@ -0,0 +1,23 @@ +/** + * A way to cancel an existing WebAuthn request, for example to cancel a + * WebAuthn autofill authentication request for a manual authentication attempt. + */ +class WebAuthnAbortService { + private controller: AbortController | undefined; + + /** + * Prepare an abort signal that will help support multiple auth attempts without needing to + * reload the page + */ + createNewAbortSignal() { + // Abort any existing calls to navigator.credentials.get() + if (this.controller) { + this.controller.abort(); + } + + this.controller = new AbortController(); + return this.controller.signal; + } +} + +export const webauthnAbortService = new WebAuthnAbortService(); diff --git a/packages/browser/src/methods/startAuthentication.ts b/packages/browser/src/methods/startAuthentication.ts index a12c8fd..6777b45 100644 --- a/packages/browser/src/methods/startAuthentication.ts +++ b/packages/browser/src/methods/startAuthentication.ts @@ -11,6 +11,7 @@ import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn'; import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsConditionalMediation'; import toPublicKeyCredentialDescriptor from '../helpers/toPublicKeyCredentialDescriptor'; import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError'; +import { webauthnAbortService } from '../helpers/webAuthnAbortService'; /** * Begin authenticator "login" via WebAuthn assertion @@ -70,6 +71,8 @@ export default async function startAuthentication( // Wait for the user to complete assertion let credential; try { + // Set up the ability to cancel this request if the user attempts another + options.signal = webauthnAbortService.createNewAbortSignal(); credential = (await navigator.credentials.get(options)) as AuthenticationCredential; } catch (err) { throw identifyAuthenticationError({ error: err as Error, options }); diff --git a/packages/browser/src/methods/startRegistration.ts b/packages/browser/src/methods/startRegistration.ts index 4037092..40a3dd9 100644 --- a/packages/browser/src/methods/startRegistration.ts +++ b/packages/browser/src/methods/startRegistration.ts @@ -10,6 +10,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'; /** * Begin authenticator "registration" via WebAuthn attestation @@ -39,6 +40,8 @@ export default async function startRegistration( // Wait for the user to complete attestation let credential; try { + // Set up the ability to cancel this request if the user attempts another + options.signal = webauthnAbortService.createNewAbortSignal(); credential = (await navigator.credentials.create(options)) as RegistrationCredential; } catch (err) { throw identifyRegistrationError({ error: err as Error, options }); -- cgit v1.2.3