Skip to content

Commit

Permalink
Fixes for nsatragno review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdavidmills committed Jan 17, 2025
1 parent 65bb980 commit 0567dad
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ To avoid this issue, `signalAllAcceptedCredentials()` should be called on the re
> [!WARNING]
> Exercise caution when invoking `signalAllAcceptedCredentials()` — any valid credentials not included in the list are intended to be removed from the authenticator, which will prevent the user from signing in with them. Passing an empty list may remove all of the user's credentials. Some authenticators may support restoring credentials via a subsequent call to `signalAllAcceptedCredentials()` with the previously removed credential IDs included in the list.
### `signalAllAcceptedCredentials()` versus `signalUnknownCredential()`

It may seem like `signalAllAcceptedCredentials()` and {{domxref("PublicKeyCredential.signalUnknownCredential_static", "PublicKeyCredential.signalUnknownCredential()")}} have similar purposes, so which one should be used when?

To be clear, `signalAllAcceptedCredentials()` should only be used in cases where authentication is _successful_ and you want to update the state of a user's credentials. Don't use it in cases where authentication failed, for example because the user deleted a credential from the relying party but later tried to sign in with it because it was still showing in the authenticator. Using `signalAllAcceptedCredentials()` for this purpose would share the entire list of `credentialId`s for a given user with an unauthenticated party, which may not be desirable.

In cases where authentication _failed_, you should instead use `signalUnknownCredential()`. It only passes a single `credentialId` to the authenticator, minimizing the data shared with an unauthenticated party.

## Syntax

```js-nolint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ It is possible for the information stored in a user's authenticator about a [dis

The next time they try to sign in with a discoverable credential, the deleted credential will still be presented in the relevant UI, but the attempt to sign in will fail because the server won't recognize it. This results in a confusing user experience.

`signalUnknownCredential()` can then be called on the relying party site to tell the authenticator that the credential ID was not recognized. It is up to the authenticator how to handle this information, but the expectation is that it will delete the relevant credential so that the same confusion does not occur again.
After this happens, `signalUnknownCredential()` can be called on the relying party site to tell the authenticator that the credential ID was not recognized. It is up to the authenticator how to handle this information, but the expectation is that it will delete the relevant credential so that the same confusion does not occur again.

### `signalUnknownCredential()` versus `signalAllAcceptedCredentials()`

It may seem like `signalUnknownCredential()` and {{domxref("PublicKeyCredential.signalAllAcceptedCredentials_static", "PublicKeyCredential.signalAllAcceptedCredentials()")}} have similar purposes, so which one should be used when?

To be clear, `signalUnknownCredential()` should be used to update the authenticator when authentication _failed_. It only passes a single `credentialId` to the authenticator, minimizing the data shared with an unauthenticated party. Using `signalAllAcceptedCredentials()` for this purpose would share the entire list of `credentialId`s for a given user with an unauthenticated party, which may not be desirable.

`signalAllAcceptedCredentials()` should be used in cases where authentication is _successful_ and you want to update the state of a user's credentials.

## Syntax

Expand Down
8 changes: 4 additions & 4 deletions files/en-us/web/api/web_authentication_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ WebAuthn uses [asymmetric (public-key) cryptography](https://en.wikipedia.org/wi
- **Reduced impact of data breaches:** Developers don't need to hash the public key, and if an attacker gets access to the public key used to verify the authentication, it can't authenticate because it needs the private key.
- **Invulnerable to password attacks:** Some users might reuse passwords, and an attacker may obtain the user's password for another website (e.g. via a data breach). Also, text passwords are much easier to brute-force than a digital signature.

Many websites already have pages that allow users to register new accounts or sign into an existing account, and WebAuthn acts as a replacement or enhancement for the authentication part of the system. It extends the [Credential Management API](/en-US/docs/Web/API/Credential_Management_API), abstracting communication between the user agent and an authenticator and providing the following new functionality:
Many websites already have pages that allow users to register new accounts or log into an existing account, and WebAuthn acts as a replacement or enhancement for the authentication part of the system. It extends the [Credential Management API](/en-US/docs/Web/API/Credential_Management_API), abstracting communication between the user agent and an authenticator and providing the following new functionality:

- When {{domxref("CredentialsContainer.create()", "navigator.credentials.create()")}} is used with the `publicKey` option, the user agent creates new credentials via an authenticator — either for registering a new account or for associating a new asymmetric key pair with an existing account.
- When registering a new account, these credentials are stored on a server (also referred to as a service or a [relying party](https://en.wikipedia.org/wiki/Relying_party)) and can be subsequently used to log a user in.
Expand Down Expand Up @@ -117,13 +117,13 @@ A typical authentication flow is as follows:

### Discoverable credentials and conditional mediation

A **discoverable credential** is one where the relying party server does not provide credential IDs. Instead, the credential IDs are stored in and provided by a client-side authenticator of some kind such as a browser password manager, authenticator app, or hardware solution such as a YubiKey.
A **discoverable credential** is one that stores credential IDs and associated metadata such as user names and display names in a client-side authenticator of some kind such as a browser password manager, authenticator app, or hardware solution such as a YubiKey. Having this information available in the authenticator means that the relying party does not have to provide a `credentialId` when asserting it, although it can do if desired in the same way as you would for a non-discoverable credential.

A discoverable credential is created via a [`create()`](/en-US/docs/Web/API/CredentialsContainer/create) call with a specified [`residentKey`](/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#residentkey), and then subsequently used for authentication via a [`get()`](/en-US/docs/Web/API/CredentialsContainer/get) call with **conditional mediation** specified, that is, [`mediation`](/en-US/docs/Web/API/CredentialsContainer/get#mediation) set to `conditional`.

You can check whether conditional mediation is available on a specific user agent by calling the {{domxref("PublicKeyCredential.isConditionalMediationAvailable()")}} method.

Conditional mediation results in discoverable credentials being presented to the user in a non-modal dialog box along with an indication of the origin requesting credentials. In practice, this means autofilling available credentials in your login forms. To display discoverable credentials in your login forms, you also need to include [`autocomplete="webauthn"`](/en-US/docs/Web/HTML/Attributes/autocomplete#webauthn) on your form fields.
Conditional mediation results in discoverable credentials being presented to the user in a non-modal dialog box along with an indication of the origin requesting credentials. In practice, this means autofilling available credentials in your login forms. The metadata stored in discoverable credentials can be displayed to help users choose a credential when logging in. To display discoverable credentials in your login forms, you also need to include [`autocomplete="webauthn"`](/en-US/docs/Web/HTML/Attributes/autocomplete#webauthn) on your form fields.

[Passkeys](https://passkeys.dev/) are a significant use case for discoverable credentials; see [Create a passkey for passwordless logins](https://web.dev/articles/passkey-registration) and [Sign in with a passkey through form autofill](https://web.dev/articles/passkey-form-autofill) for implementation details. See also [Discoverable credentials deep dive](https://web.dev/articles/webauthn-discoverable-credentials) for more general information on discoverable credentials.

Expand Down Expand Up @@ -205,7 +205,7 @@ If you wish to authenticate with `get()` or `create()` in an `<iframe>`, there a
- {{domxref("AuthenticatorResponse")}}
- : The base interface for {{domxref("AuthenticatorAttestationResponse")}} and {{domxref("AuthenticatorAssertionResponse")}}.
- {{domxref("PublicKeyCredential")}}
- : Provides information about a public key / private key pair, which is a credential for logging in to a service using an un-phishable and data-breach resistant asymmetric key pair instead of a password. Obtained when the {{jsxref("Promise")}} returned via a {{domxref("CredentialsContainer.create", "create()")}} or {{domxref("CredentialsContainer.get", "get()")}} call fulfills.
- : Provides information about a public key / private key pair, which is a credential for logging into a service using an un-phishable and data-breach resistant asymmetric key pair instead of a password. Obtained when the {{jsxref("Promise")}} returned via a {{domxref("CredentialsContainer.create", "create()")}} or {{domxref("CredentialsContainer.get", "get()")}} call fulfills.

## Extensions to other interfaces

Expand Down

0 comments on commit 0567dad

Please sign in to comment.