Skip to content

Commit

Permalink
[accounts] Restore the workaround for Safari
Browse files Browse the repository at this point in the history
This restores the workaround I'd removed in
4d84e96.

    listItem.transports = ["usb", "nfc", "ble", "internal"];

- This PR fixes the passkey verification on Safari.

- Sibling PR that fixes the passkey registration: https://github.com/ente-io/ente/pull/2429/files
  • Loading branch information
mnvr committed Jul 12, 2024
1 parent e881c15 commit 7047383
Showing 1 changed file with 55 additions and 1 deletion.
56 changes: 55 additions & 1 deletion web/apps/accounts/src/services/passkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,61 @@ export const beginPasskeyAuthentication = async (
*/
export const signChallenge = async (
publicKey: PublicKeyCredentialRequestOptions,
) => nullToUndefined(await navigator.credentials.get({ publicKey }));
) => {
// Hint all transports to make security keys like Yubikey work across
// varying registration/verification scenarios.
//
// During verification, we need to pass a `transport` property.
//
// > The `transports` property is hint of the methods that the client could
// > use to communicate with the relevant authenticator of the public key
// > credential to retrieve. Possible values are ["ble", "hybrid",
// > "internal", "nfc", "usb"].
// >
// > MDN
//
// When we register a passkey, we save the transport alongwith the
// credential. During authentication, we pass that transport back to the
// browser. This is the approach recommended by the spec:
//
// > When registering a new credential, the Relying Party SHOULD store the
// > value returned from getTransports(). When creating a
// > PublicKeyCredentialDescriptor for that credential, the Relying Party
// > SHOULD retrieve that stored value and set it as the value of the
// > transports member.
// >
// > https://www.w3.org/TR/webauthn-3/#dom-publickeycredentialdescriptor-transports
//
// However, following this recommendation break things currently (2024) in
// various ways. For example, if a user registers a Yubikey NFC security key
// on Firefox on their laptop, then Firefox returns ["usb"]. This is
// incorrect, it should be ["usb", "nfc"] (which is what Chrome does, since
// the hardware itself supports both USB and NFC transports).
//
// Later, if the user tries to verifying with their security key on their
// iPhone Safari via NFC, the browser doesn't recognize it (which seems
// incorrect too, the transport is meant to be a "hint" not a binding).
//
// > Note that these hints represent the WebAuthn Relying Party's best
// > belief as to how an authenticator may be reached.
// >
// > https://www.w3.org/TR/webauthn-3/#dom-publickeycredentialdescriptor-transports
//
// As a workaround, we override transports with known possible values.

for (const cred of publicKey.allowCredentials ?? []) {
cred.transports = [
...(cred.transports ?? []),
"usb",
"nfc",
"ble",
"hybrid",
"internal",
];
}

return nullToUndefined(await navigator.credentials.get({ publicKey }));
};

interface FinishPasskeyAuthenticationOptions {
passkeySessionID: string;
Expand Down

0 comments on commit 7047383

Please sign in to comment.