Fehlermeldung
InvalidStateError: The user attempted to register an authenticator that contains one of the credentials already registered with the relying party.
Oben steht der Text von Chromium; andere Browser formulieren es anders. Der DOMException-Name `InvalidStateError` ist der stabile Teil.
WebAuthn navigator.credentials.create() with excludeCredentials — DOMException InvalidStateError (Chromium)
Was der Fehler bedeutet
Die Registrierung wurde abgelehnt, weil der Authenticator bereits eines der Credentials enthält, die du in `excludeCredentials` aufgeführt hast. Eine Relying Party sendet diese Liste genau deshalb, damit derselbe Authenticator nicht zweimal für ein Konto registriert wird – meist ist das also das gewollte Ergebnis: Der Nutzer hat auf diesem Gerät bereits einen funktionierenden Passkey. Browser verraten das erst, nachdem der Nutzer mit dem Authenticator interagiert hat.
Warum der Fehler auftritt
Der Nutzer hat auf demselben Gerät erneut auf „Passkey hinzufügen“ geklickt
häufigDer häufigste Fall. Das Konto hat auf diesem Authenticator bereits ein Credential; die richtige Antwort darauf ist, die Anmeldung damit anzubieten.
Ein synchronisierter Passkey ist auf diesem Gerät angekommen
häufigiCloud-Schlüsselbund, Google Passwortmanager und andere Passkey-Anbieter synchronisieren Credentials. Ein auf dem Smartphone registrierter Passkey ist auch auf dem Laptop vorhanden, daher wird die Registrierung „des Laptops“ ausgeschlossen.
Die Ausschlussliste enthält Credentials anderer Nutzer
gelegentlichEin Bug, der alle Credentials aufführt (oder die eines anderen Kontos, das dasselbe Gerät nutzt), blockiert Registrierungen, die gelingen sollten.
So behebst du den Fehler
- 1.
Dem Nutzer sagen, dass schon alles eingerichtet ist
Behandle InvalidStateError als „hier gibt es schon einen Passkey“ und führe den Nutzer zur Anmeldung damit.
js try { const credential = await navigator.credentials.create({ publicKey: options }); await saveCredential(credential); } catch (e) { if (e.name === "InvalidStateError") { showMessage("This device already has a passkey for your account. You can use it to sign in."); } else if (e.name !== "NotAllowedError") { throw e; } } - 2.
Nur die Credentials des aktuellen Nutzers ausschließen
Baue `excludeCredentials` aus den gespeicherten Credential-IDs des angemeldeten Nutzers auf und verwende pro Konto eine stabile, zufällige `user.id`.
js // Server: exclude only the CURRENT user's credentials (base64url ids from your database). const options = await generateRegistrationOptions({ rpName: "Example", rpID, userName: user.email, userID: user.webauthnUserId, // stable per user, never the email excludeCredentials: user.passkeys.map((p) => ({ id: p.credentialId, transports: p.transports })), });