Skip to content

Preventing duplicate passkey registration via 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.

You 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:

import { registerPasskey, isDuplicatePasskeyError } from "@passlock/client";
// from your backend database
const excludeCredentials = [existingPasskeyId];
try {
const result = await registerPasskey({ excludeCredentials, ... });
} catch (e) {
if (isDuplicatePasskeyError(e)) {
alert("You already have a suitable passkey on this device");
}
}

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 across a platform/ecosystem e.g. Apple and to devices using a common cloud id.

If 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). Their 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.