From a2397e46aa543681e9a7185fc1c66ce833f7e2cf Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 12 Jul 2026 13:54:55 +0530 Subject: [PATCH 1/3] fix(passkey): dismiss cancel / no-passkey silently, let user skip The "Sign in with a passkey" button is always shown when the browser supports WebAuthn - including for users who have no passkey - so a cancel or an account-with-no-passkey (both surface as NotAllowedError/AbortError) was showing a red "cancelled or failed" error. Treat those as a silent skip so the user just falls back to password/social login; only surface real failures. --- src/components/AuthorizerPasskeyLogin.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/AuthorizerPasskeyLogin.tsx b/src/components/AuthorizerPasskeyLogin.tsx index 0df930c..22736da 100644 --- a/src/components/AuthorizerPasskeyLogin.tsx +++ b/src/components/AuthorizerPasskeyLogin.tsx @@ -47,13 +47,24 @@ export const AuthorizerPasskeyLogin: FC<{ const hasAnotherLoginMethod = hasSocialLogin || hasBasicAuthLogin || config.is_magic_link_login_enabled; + // A cancelled ceremony or an account with no passkey surfaces as + // NotAllowedError/AbortError (the browser deliberately does not distinguish + // "cancelled" from "no credential" to avoid leaking account state). Neither is + // a real failure - the user simply falls back to password/social login - so we + // dismiss silently instead of showing a scary error banner. The button is + // always visible when the browser supports WebAuthn, so this path is common. + const isUserDismissed = (e?: { code?: string }): boolean => + e?.code === `NotAllowedError` || e?.code === `AbortError`; + const onClick = async () => { setError(``); try { setLoading(true); const { data: res, errors } = await authorizerRef.loginWithPasskey(); if (errors && errors.length) { - setError(errors[0]?.message || ``); + if (!isUserDismissed(errors[0])) { + setError(errors[0]?.message || ``); + } return; } if (res) { @@ -68,7 +79,9 @@ export const AuthorizerPasskeyLogin: FC<{ onLogin(res); } } catch (err) { - setError((err as Error).message); + if (!isUserDismissed(err as { code?: string })) { + setError((err as Error).message); + } } finally { setLoading(false); } From 60c46ddfeca3fab36c37004f92ef2a5071b9ddb3 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 12 Jul 2026 15:06:39 +0530 Subject: [PATCH 2/3] feat(passkey): add key icon to the passkey sign-in button --- src/components/AuthorizerPasskeyLogin.tsx | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/components/AuthorizerPasskeyLogin.tsx b/src/components/AuthorizerPasskeyLogin.tsx index 22736da..5e3d4f2 100644 --- a/src/components/AuthorizerPasskeyLogin.tsx +++ b/src/components/AuthorizerPasskeyLogin.tsx @@ -13,6 +13,28 @@ import { Message } from './Message'; // WebAuthn JSON ceremony APIs the SDK relies on - there is no server-side // config flag for passkeys (unlike social login), it's purely a browser // capability. +// PasskeyIcon is an inline key glyph (no icon-library dependency) that inherits +// the button's text color via currentColor. +const PasskeyIcon: FC = () => ( + +); + export const AuthorizerPasskeyLogin: FC<{ onLogin?: (data: AuthToken | void) => void; }> = ({ onLogin }) => { @@ -99,7 +121,17 @@ export const AuthorizerPasskeyLogin: FC<{ disabled={loading} appearance={ButtonAppearance.Default} > - {loading ? `Waiting for passkey ...` : `Sign in with a passkey`} + + + {loading ? `Waiting for passkey ...` : `Sign in with a passkey`} + {hasAnotherLoginMethod && OR} From 6a2a2a5b41dac922fe8d588bf16829b3c5caa465 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 12 Jul 2026 15:08:19 +0530 Subject: [PATCH 3/3] fix(passkey): use fingerprint icon on the passkey sign-in button --- src/components/AuthorizerPasskeyLogin.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/components/AuthorizerPasskeyLogin.tsx b/src/components/AuthorizerPasskeyLogin.tsx index 5e3d4f2..bb29d1e 100644 --- a/src/components/AuthorizerPasskeyLogin.tsx +++ b/src/components/AuthorizerPasskeyLogin.tsx @@ -13,8 +13,8 @@ import { Message } from './Message'; // WebAuthn JSON ceremony APIs the SDK relies on - there is no server-side // config flag for passkeys (unlike social login), it's purely a browser // capability. -// PasskeyIcon is an inline key glyph (no icon-library dependency) that inherits -// the button's text color via currentColor. +// PasskeyIcon is an inline fingerprint glyph (no icon-library dependency) that +// inherits the button's text color via currentColor. const PasskeyIcon: FC = () => ( ( aria-hidden="true" focusable="false" > - - - - + + + + + + + + + );