Skip to content

Preventing duplicate passkey registration (excludeCredentials)

Passkeys are typically synced across devices sharing the same cloud account ID e.g. a MacBook and iPhone signed into the same iCloud ID. Therefore you typically wouldn’t want a user to create one passkey on their iPhone and one on their MacBook, as they’d end up with two passkeys on both devices.

To prevent the user from creating multiple passkeys on a device, pass the existing passkey ids during the registerPasskey call and test for a DuplicatePasskey error:

frontend/register.ts
import {
registerPasskey,
isRegistrationSuccess,
isDuplicatePasskey
} from "@passlock/client";
// from your backend database
const excludeCredentials = [existingPasskeyId];
const result = await registerPasskey({ excludeCredentials, ... });
if (isRegistrationSuccess(result)) {
// happy days
} else if (isDuplicatePasskey(result)) {
alert("You already have a passkey on this device")
} else { ... }

The same user may want to log into your system using multiple accounts e.g. personal and work. Make sure you only pass passkey IDs related to the same login account as it’s quite legitimate for them to register multiple passkeys for different user accounts.

Whilst passkeys are synced across devices, this only applies to common platforms/ecosystems (e.g. Apple or Google) and to devices sharing a common cloud id.

Imagine a user registers a passkey using their personal iPhone, it will be linked to their personal MacBook and iPad but not their work desktop or notebook.

They might want to use the roaming authenticator flow to sign in using their work device, then register a passkey on that device. In this case you would pass the existing passkey ID (linked to their personal iCloud account), and the work device will ignore it, and allow them to register a second passkey.

However if the user tries to register a passkey on one of their personal devices they would receive an error telling them that a passkey already exists.