Agent Wranglers

Sign-in methods Optional

Keep the password manager's passkey list current

Tell the browser when a passkey stops working or a user's name changes, with the WebAuthn signal methods, so people stop picking dead passkeys.

How to do it

When sign-in fails because the credential ID is unknown, call PublicKeyCredential.signalUnknownCredential(). After someone deletes a passkey in settings, call signalAllAcceptedCredentials() with the IDs that remain. After a change of email or display name, call signalCurrentUserDetails(). Test that each method exists first, because older browsers lack them. The server sends the lists, so it stays the source of truth.

Example

async function afterPasskeyDeleted() {
  if (!PublicKeyCredential.signalAllAcceptedCredentials) return;
  const accepted = await (await fetch('/passkeys/accepted')).json();
  await PublicKeyCredential.signalAllAcceptedCredentials(accepted);
}
from webauthn.helpers import bytes_to_base64url

@app.get("/passkeys/accepted")
def accepted_passkeys(user=Depends(current_user)):
    return {
        "rpId": "example.com",
        "userId": bytes_to_base64url(user.webauthn_handle),
        "allAcceptedCredentialIds": [bytes_to_base64url(p.credential_id) for p in user.passkeys],
    }

How to check

A browser test deletes a passkey in settings and spies on signalAllAcceptedCredentials. It is called once, with every remaining ID and without the deleted one.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers accounts playbook: https://agentwranglers.se/playbook/accounts/sign-in-methods/passkey-signals.