Merge pull request #2756 from basecamp/friendly-error-message-on-duplicate-passkey

Show separate error message when adding a Passkey twice
This commit is contained in:
Stanko Krtalić
2026-03-26 14:19:35 +01:00
committed by GitHub
parent 527f2e07ff
commit 09d5b8c92f
3 changed files with 29 additions and 9 deletions
+14 -5
View File
@@ -77,9 +77,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 type = errorType(error)
this.#showError(type)
this.button.dispatchEvent(new CustomEvent("passkey:error", { bubbles: true, detail: { error, type } }))
}
#showError(type) {
@@ -139,8 +139,8 @@ class PasskeySignInButton extends PasskeyButton {
this.form.submit()
} catch (error) {
console.error("Passkey conditional mediation failed", error)
const cancelled = error.name === "AbortError" || error.name === "NotAllowedError"
this.button.dispatchEvent(new CustomEvent("passkey:error", { bubbles: true, detail: { error, cancelled } }))
const type = errorType(error)
this.button.dispatchEvent(new CustomEvent("passkey:error", { bubbles: true, detail: { error, type } }))
}
}
}
@@ -157,6 +157,15 @@ customElements.define("rails-passkey-sign-in-button", PasskeySignInButton)
// -- Shared helpers ----------------------------------------------------------
function errorType(error) {
switch (error.name) {
case "AbortError":
case "NotAllowedError": return "cancelled"
case "InvalidStateError": return "duplicate"
default: return "error"
}
}
function passkeysAvailable() {
return !!window.PublicKeyCredential
}
+1 -1
View File
@@ -18,7 +18,7 @@
<% end %>
<footer>
<%= passkey_registration_button my_passkeys_path, options: @registration_options, error: { class: "txt-negative margin-block-half" }, cancellation: { class: "txt-subtle margin-block-half" }, class: "btn btn--link center txt-medium" do %>
<%= passkey_registration_button my_passkeys_path, options: @registration_options, error: { class: "txt-negative margin-block-half" }, cancellation: { class: "txt-subtle margin-block-half" }, duplicate: { class: "txt-negative margin-block-half" }, class: "btn btn--link center txt-medium" do %>
<%= icon_tag "add" %>
<span>Register a passkey</span>
<% end %>