Bug 261301 - WebAuthn auth always shows hybrid QR code when only "internal" transport in allowCredentials but no credentials recognized by platform
Summary: WebAuthn auth always shows hybrid QR code when only "internal" transport in a...
Status: RESOLVED MOVED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Misc. (show other bugs)
Version: Safari 16
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2023-09-07 16:49 PDT by matthew
Modified: 2024-06-24 15:52 PDT (History)
8 users (show)

See Also:


Attachments
Hybrid auth QR code shown in iOS Safari (139.29 KB, image/png)
2023-09-07 16:49 PDT, matthew
no flags Details
"No passkeys available" message shown by Chrome for same scenario (20.16 KB, image/png)
2023-09-07 16:50 PDT, matthew
no flags Details
iOS prompt to turn on iCloud Keychain sync during registration (737.11 KB, image/jpeg)
2023-09-08 10:14 PDT, matthew
no flags Details
macOS prompt to turn on iCloud Keychain sync during registration (42.85 KB, image/png)
2023-09-08 10:15 PDT, matthew
no flags Details
Retesting in Safari 17.2.1 on macOS 14.2.1 (74.67 KB, image/png)
2023-12-21 15:35 PST, matthew
no flags Details
The issue continues in Safari 17.5 on macOS 14.5 (228.89 KB, image/png)
2024-06-24 14:30 PDT, matthew
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description matthew 2023-09-07 16:49:04 PDT
## Context

Safari 16 on iOS and macOS (and probably iPadOS too) always shows the hybrid auth QR code in cases where no entries in allowCredentials, with only ["internal"] specified for their transports, are recognized by the local platform authenticator.

As an RP, if we do not communicate to the browser that "hybrid" transport is possible for any provided credentials we would not expect the QR code to appear. For sake of comparison, Chrome on macOS and Android shows a "no passkeys available" message in this same scenario.

## Environment

- Safari 16.6
- macOS 13.5.1
- iOS 16.6

## Reproduction

This basic HTML document can be used to recreate the scenario outlined above:

```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">
  <style>
    body {
      max-width: 40em;
      margin: auto;
    }
  </style>
  <title>Safari Bug - Hybrid shown for unrecognized ["internal"] entry in allowCredentials</title>
</head>
<body>
  <h1>
    Safari Bug - Hybrid shown for unrecognized ["internal"] entry in allowCredentials
  </h1>
  <p>
    Demonstrating how Safari shows hybrid auth QR code as an option even though the only entry in
    allowCredentials has just ["internal"] for its transports.
  </p>
  <button id="auth1">Authenticate w/["internal"]</button>
  <script>
    // button#auth1
    document.getElementById('auth1').addEventListener('click', () => {
      navigator.credentials.get({
        publicKey: {
          challenge: new Uint8Array([1,2,3,4]),
          allowCredentials: [
            { id: new Uint8Array([1]), type: 'public-key', transports: ['internal'] },
          ]
        },
      }).then(console.log);
    });
  </script>
</body>
</html>
```
Comment 1 matthew 2023-09-07 16:49:46 PDT
Created attachment 467593 [details]
Hybrid auth QR code shown in iOS Safari
Comment 2 matthew 2023-09-07 16:50:16 PDT
Created attachment 467594 [details]
"No passkeys available" message shown by Chrome for same scenario
Comment 3 Radar WebKit Bug Importer 2023-09-07 17:06:01 PDT
<rdar://problem/115144326>
Comment 4 pascoe@apple.com 2023-09-08 09:47:51 PDT
If a credential is available over "internal," then it follows that it would also be available over hybrid if it's on another device's platform authenticator.
Comment 5 Tim Cappalli 2023-09-08 09:52:04 PDT
John - if a credential is also available over hybrid, it should have both `internal` and `hybrid` transports. It can't be assumed that internal and hybrid are always coupled.
Comment 6 matthew 2023-09-08 10:13:35 PDT
> If a credential is available over "internal," then it follows that it would also be available over hybrid if it's on another device's platform authenticator.

A specific pain point with this line of reasoning is that, if a passkey is registered via macOS Safari, but iCloud Keychain sync is OFF in iOS, then there's no way to scan the QR code that iOS shows by any device running macOS. It seems like an impossible scenario for a user to complete auth in because of macOS' lack of a OS-level way to scan QR codes.

There's an alternative idea that came up this morning: what if Safari consistently showed the same prompt to enable iCloud Keychain sync that it shows during registration, but during authentication as well? If Safari is given a credential with ["internal", "hybrid"] then how can it test if the platform authenticator on the iOS device recognizes it if iCloud Keychain sync (which still seems to be a hard requirement to use a platform authenticator on an Apple device) is disabled?

I'm going to attach a couple screenshots of the registration CTA to turn on sync that I think could also unstick users here.
Comment 7 matthew 2023-09-08 10:14:38 PDT
Created attachment 467605 [details]
iOS prompt to turn on iCloud Keychain sync during registration
Comment 8 matthew 2023-09-08 10:15:02 PDT
Created attachment 467606 [details]
macOS prompt to turn on iCloud Keychain sync during registration
Comment 9 matthew 2023-09-08 10:16:12 PDT
For the record, I'd still prefer Safari to act like Chrome and show a "no passkeys available" when ["internal"] is unrecognized by the access device.
Comment 10 Brent Fulgham 2023-12-21 15:14:34 PST
The fix for this issue needs to be made outside of the WebKit Open Source project. Resolving as MOVED.

We believe this has been resolved in the now-shipping iOS 17.2 and macOS 14.2 releases.
Comment 11 matthew 2023-12-21 15:35:10 PST
I retested just now in Safari 17.2.1 on macOS 14.2.1. Now if I try to authenticate with the same example as above then nothing happens at all - there's no visual indication that a WebAuthn call was ever attempted.

When I view try again while looking at the console in Web Inspector there's a single `NotAllowedError: Operation failed" and nothing else to help either user or RP understand that this call to `.get()` is erroring out because the platform authenticator doesn't recognize the only allowed credential?

I've attached a screenshot with this error visible.

Can you please confirm that this the new expected behavior?
Comment 12 matthew 2023-12-21 15:35:35 PST
Created attachment 469164 [details]
Retesting in Safari 17.2.1 on macOS 14.2.1
Comment 13 Brent Fulgham 2024-06-03 10:50:02 PDT
I just reviewed the radar referenced here, and I show this fix as having shipped in iOS 17.3 and macOS 14.3.
Comment 14 matthew 2024-06-24 14:30:39 PDT
Created attachment 471735 [details]
The issue continues in Safari 17.5 on macOS 14.5

Apologies but I have to reopen this, I just tested the HTML above in Safari 17.5 on macOS 14.5 and I'm still shown a QR code. Please see the latest screenshot I took this afternoon.
Comment 15 matthew 2024-06-24 14:31:22 PDT
Reopening because of potential regression.
Comment 16 Brent Fulgham 2024-06-24 14:37:35 PDT
Fix is still outside of WebKit, so setting to MOVED.
Comment 17 Brent Fulgham 2024-06-24 14:39:51 PDT
The regression claim will be tracked by:
rdar://130446659
Comment 18 matthew 2024-06-24 15:52:15 PDT
> Fix is still outside of WebKit, so setting to MOVED.

Ah, "MOVED" means that this may be an issue at the Safari level instead?