Bug 257176

Summary: WebAuthn .create() rejects with "NotAllowedError: Operation Failed" after conditional UI request aborted
Product: WebKit Reporter: matthew
Component: WebKit Misc.Assignee: Abigail F <abigail_fox>
Status: RESOLVED FIXED    
Severity: Normal CC: bfulgham, pascoe, webkit-bug-importer, wilander
Priority: P2 Keywords: InRadar
Version: Safari 16   
Hardware: Mac (Apple Silicon)   
OS: macOS 13   
Bug Depends on:    
Bug Blocks: 271257    

Description matthew 2023-05-22 19:06:12 PDT
## Context

I'm observing Safari rejecting a call to `navigator.credentials.create()` with "NotAllowedError: Operation Failed" when the active page has an active conditional UI request.

## Environment

- macOS 13.4
- Safari 16.5

## Reproduction Steps

1. Host the following HTML file on http://localhost (see the end of this description)
2. Observe conditional UI is active on the lone text input
3. Open Safari dev tools
4. Click the "Start modal registration" button
5. Observe the expected "AbortError: Aborted by AbortSignal" error
6. After a short delay, observe the unexpected "NotAllowedError: Operation failed" error and no WebAuthn registration modal
7. Refresh the page
8. Click the "Start modal authentication" button
9. Observe the expected "AbortError: Aborted by AbortSignal" error
10. Observe the typical Safari WebAuthn authentication modal

### Sample code

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button id="startReg">Start modal registration</button>
    <button id="startAuth">Start modal authentication</button>
    <form action="">
      <input
        type="email"
        name="email"
        id="email"
        autocomplete="webauthn username"
      />
    </form>
    <script>
      const abortController = new AbortController();

      // 1. Start conditional UI
      navigator.credentials
        .get({
          publicKey: {
            challenge: new Uint8Array(16).fill(0),
            allowCredentials: [],
          },
          mediation: "conditional",
          signal: abortController.signal,
        })
        .then(console.log)
        .catch(console.error);

      // 2. Click to start modal registration (errors out with "NotAllowedError: Operation Failed")
      document.getElementById("startReg").addEventListener("click", () => {
        abortController.abort(
          new Error("cancelling conditional UI for registration")
        );
        navigator.credentials.create({
          publicKey: {
            challenge: new Uint8Array(16).fill(0),
            rp: { id: "localhost", name: "localhost" },
            user: {
              id: new Uint8Array(16).fill(0),
              name: "Username",
              displayName: "Username",
            },
            pubKeyCredParams: [{ alg: -7, type: "public-key" }],
          },
        });
      });

      // 3. Click to start modal authentication (it works as expected)
      document.getElementById("startAuth").addEventListener("click", () => {
        abortController.abort(
          new Error("cancelling conditional UI for authentication")
        );
        navigator.credentials.get({
          publicKey: {
            challenge: new Uint8Array(16).fill(0),
          },
        });
      });
    </script>
  </body>
</html>
```

## Expected Behavior

I was expecting the conditional UI request to reject with the AbortError, and then Safari to show the typical registration modal.
Comment 1 Radar WebKit Bug Importer 2023-05-27 18:37:34 PDT
<rdar://problem/109936742>
Comment 2 Abigail F 2024-01-19 10:49:26 PST
Pull request: https://github.com/WebKit/WebKit/pull/22983
Comment 3 EWS 2024-02-01 09:35:05 PST
Committed 273918@main (ded025f42cde): <https://commits.webkit.org/273918@main>

Reviewed commits have been landed. Closing PR #22983 and removing active labels.