From c53e7f762d9582c9226a95d30643a4558b4a7572 Mon Sep 17 00:00:00 2001 From: "Stanko K.R." Date: Thu, 26 Mar 2026 13:44:44 +0100 Subject: [PATCH 1/3] Show separate error message when adding a Passkey twice Turns out Google Passwords doesn't obey the exvlude list and allows only a single passkey per RP ID. If you try to add a new Passkey after you already created one in Google Passwords it will cause a client-side state error, which per spec can only mean that someone tried to re-add the same passkey twice and the client detected that. --- app/javascript/lib/action_pack/passkey.js | 5 +++-- app/views/my/passkeys/index.html.erb | 2 +- lib/action_pack/passkey/form_helper.rb | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/javascript/lib/action_pack/passkey.js b/app/javascript/lib/action_pack/passkey.js index 7ee20cb84a..ae94a955ca 100644 --- a/app/javascript/lib/action_pack/passkey.js +++ b/app/javascript/lib/action_pack/passkey.js @@ -78,8 +78,9 @@ class PasskeyButton extends HTMLElement { #handleError(error) { console.error("Passkey ceremony failed", error) const cancelled = error.name === "AbortError" || error.name === "NotAllowedError" - this.#showError(cancelled ? "cancelled" : "error") - this.button.dispatchEvent(new CustomEvent("passkey:error", { bubbles: true, detail: { error, cancelled } })) + const duplicate = error.name === "InvalidStateError" + this.#showError(duplicate ? "duplicate" : cancelled ? "cancelled" : "error") + this.button.dispatchEvent(new CustomEvent("passkey:error", { bubbles: true, detail: { error, cancelled, duplicate } })) } #showError(type) { diff --git a/app/views/my/passkeys/index.html.erb b/app/views/my/passkeys/index.html.erb index de143eeb41..fea08c27bf 100644 --- a/app/views/my/passkeys/index.html.erb +++ b/app/views/my/passkeys/index.html.erb @@ -18,7 +18,7 @@ <% end %>