[webauthn] Add onlyCreate to prevent creation of a new key for existing user (#2313)

mitar has just created a new issue for https://github.com/w3c/webauthn:

== Add onlyCreate to prevent creation of a new key for existing user ==
## Use case

The use case is simple. Having an app with one button "Sign-in with passkey". If user does not have an account with their device, one is created for them. If they do have, they are signed-in. No username, no user ID. User authenticated by having access to the device and being able to use it to do the authentication flow using WebAuthn.

User account on the RP side is created after authenticating for the first time. This is the why residential/discoverable keys are great. The only issue currently is, you or user can override them by accident if RP does a "create" call when key is in fact present.

The point is, why would username be required, if one has (discoverable) credential ID to determine the user account on the RP side. It works great. Except for the "override by accident" situation.

## Prior proposals

* https://github.com/w3c/webauthn/issues/1749 - proposing `exists` to check if key exists
* https://github.com/w3c/webauthn/issues/1568  - proposing `getOrCreate` to create a key only if does not already exist, otherwise returning the key
* https://github.com/w3c/webauthn/issues/2309 - proposing `excludeUsers` to list user IDs for which key should not be created

## Description

After discussion in #1568 and #2309 I realized that the biggest issue of doing "get" and "create" separately is that "create" after canceled "get" could potentially override existing key. So I am proposing `onlyCreate` flag for `PublicKeyCredentialCreationOptions` which would flag to the browser that for given user ID, only a new credential should be created and if existing credential exists, `NotAllowedError` should be returned instead.

`onlyCreate` is just the first proposal for the name, I am open to any other reasonable name.

This is still a poor-man solution to native `getOrCreate` which could have superior UX made by the browser, as browser knows if user just wants to cancel the action or if the key really does not exist, etc., without having to reveal any of that to RP. But with `onlyCreate`, RP can implement the following flow, which is OKish:

* Call `get` with constant user ID and immediate mediation set.
* If it gets `NotAllowedError` call `create` with `onlyCreate` set with same constant user ID.

This works well in the sense that if user has a key, we get it with only one click. If user does not have a key, we create it. If user clicks "cancel" after "get", we do not override any key. The only issue is that if user really wants to cancel the whole flow, they have to click cancel twice, once for "get" and once for "create".

Please view or discuss this issue at https://github.com/w3c/webauthn/issues/2313 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 11 July 2025 06:59:26 UTC