Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/webauthn-abort-controller-race-condition #275

Merged
merged 2 commits into from
Sep 29, 2022

Conversation

MasterKale
Copy link
Owner

@MasterKale MasterKale commented Sep 28, 2022

This PR attempts to remove a race condition from browser's WebAuthnAbortService. It was discovered that multiple invocations of startAuthentication() in a row (especially in a SPA using clientside routing), particularly when conditional UI is started, could lead to WebAuthnAbortService.reset() being called early which would fail a subsequent call to startAuthentication() with a DOMException and "a request is already pending."

I determined that this was due to the call to this.controller.abort() not actually aborting the navigator.credentials.get() synchronously. We can't await an AbortController.abort() to wait for the navigator.credentials.get() to be aborted; we can only abort and cross our fingers that we don't call startAuthentication() until the WebAuthn API call actually terminates in response to the abort signal.

This can lead to .reset() being called by the first startAuthentication()'s try / catch / finally after a subsequent call to webauthnAbortService.createNewAbortSignal(), which expects this.controller to be populated with the new controller but ends up becoming undefined when the .reset() gets called after the first controller calls .abort(). The second call to startAuthentication() can no longer be aborted, and a third call will error out because the second WebAuthn API call is indeed still pending.

See #273 (comment), I included some logging output that might make it clearer if the above description is insufficient.

The fix is to remove the reset() method from WebAuthnAbortService. In testing I observed no issues with possibly repeatedly calling .abort() on an already-aborted controller. Thus we can leave the service's this.controller populated between calls to createNewAbortSignal() and forget about trying to tame a race condition.

Fixes #273.

Demonstration

Screen.Recording.2022-09-27.at.9.08.30.PM.mov

@MasterKale MasterKale force-pushed the fix/webauthn-abort-controller-race-condition branch from 247929c to 4ea0bd3 Compare September 28, 2022 21:51
@MasterKale MasterKale merged commit 8b75f08 into master Sep 29, 2022
@MasterKale MasterKale deleted the fix/webauthn-abort-controller-race-condition branch September 29, 2022 04:14
@MasterKale MasterKale added this to the v6.2.1 milestone Sep 29, 2022
@MasterKale MasterKale added the package:browser @simplewebauthn/browser label Sep 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package:browser @simplewebauthn/browser
Projects
None yet
Development

Successfully merging this pull request may close these issues.

multiple calling of startAuthentication in conditional autofill causes reset to clear webauthnAbortService
1 participant