Stop duplicate passkeys with excludeCredentials

When a user attempts to register a new passkey, you may want to prevent them from creating a second credential on an authenticator that already holds one for their account. WebAuthn's PublicKeyCredentialCreationOptions dictionary provides the optional excludeCredentials property for exactly this purpose.

The excludeCredentials property is an array of public key descriptors that the relying party's server provides during the registration ceremony. Each descriptor identifies a credential that already exists for the user. When the client processes the creation request, it checks the local authenticator against this list before allowing a new credential to be generated.

Each entry in the array contains two attributes:

  • type: A string describing the type of public-key credential to be generated. The default value is "public-key".
  • id: An ArrayBuffer matching an existing public key credential identifier (PublicKeyCredential.rawId), which was generated when the original credential was created.

If the user attempts to create a new credential on a platform authenticator that already contains one of the listed identifiers, the client returns an error. The authenticator still collects user consent as usual and displays a success indicator, but no new credential is actually created. Instead, an InvalidStateError exception is thrown, indicating that a valid credential matching an entry in excludeCredentials already exists for the user.

The server-side JSON payload for the creation options would look similar to the following:

"excludeCredentials": [
    {"id": "<id-1>", "type": "public-key"},
    {"id": "<id-2>", "type": "public-key"}
  ]

In this structure, each <id-*> placeholder should be replaced with the credential identifier you want to exclude from duplicate registration.

For the full specification details, refer to the W3C recommendation on excludeCredentials.