Everything beyond the core register()/login() cascade for working with passkeys directly.
Generated directly from @threshold1/auth@0.3.0 — the real, currently-installed package, not hand-typed. Regenerated on every build; if this page and the actual SDK ever disagree, the SDK is right and this page needs a rebuild, not an edit.
addPasskey(options?): Promise<{
createdAt: string;
credentialId: string;
deviceHint: string | null;
}>;
Enroll a passkey for the currently authenticated user. Call this after login() to add a passkey to an existing account.
string
Filled in on the user's record if they don't already have an email on file. An existing email is never overwritten by this call.
string
Attached to the authenticated user if they don't already have a (different) externalUserId set — the same identity-bridge upgrade rule register()/login() use elsewhere.
Promise<{
createdAt: string;
credentialId: string;
deviceHint: string | null;
}>
listPasskeys(): Promise<object[]>;
List all passkeys registered for the current user. Requires an active session.
Promise<object[]>
removePasskey(credentialId): Promise<void>;
Remove a passkey by credential ID. Requires an active session. Only removes passkeys owned by the current user.
string
The credential ID to remove (from listPasskeys())
Promise<void>
mountButton(container, options?): Promise<void>;
Mount a "Sign in with Passkey" button into the given container element. Automatically shows a "Powered by threshold1" badge for free/starter plans. The badge cannot be removed — it is required on non-paid plans.
Note: this button has no room to render an identifier input or a
confirm-to-send prompt, so onSuccess only fires for an actual
completed login. When login() instead resolves with
identifier_required or confirm_required (fallback: "smart",
the default, with no recognized/registered passkey), onError fires
with a descriptive error instead — build custom UI with login() /
confirmDeviceSend() / verifyDeviceCode() directly to handle those states.
HTMLElement
A DOM element to render the button into
Optional label, callbacks, and className
Promise<void>
enableConditionalUI(input): Promise<LoginResult | null>;
Arm conditional UI (passkey autofill) on the given identifier input. Call this once the input is mounted (e.g. on page load) — it does not block and shows no UI of its own; the browser's native autofill dropdown handles that entirely once the user focuses/types in the field.
Resolves to null (never throws) when the browser doesn't support
conditional mediation (per PublicKeyCredential.isConditionalMediationAvailable()) —
fall through to your existing explicit "Continue with passkey"
button/mountButton() in that case, unchanged. Also resolves to null
when the ceremony is aborted (e.g. this is called again, or
cancelConditionalUI() is called) — that's expected re-arm behavior,
not an error.
Resolves to { method: "passkey", status: "success" } once the user
picks a suggestion and the server verifies it — fires
auth.onAfterAuth("passkey") exactly like every other successful
passkey login.
NOTE: this can only be meaningfully exercised in a real browser with a real saved passkey and OS-level autofill UI — no automated test can simulate that dropdown. See the SDK playground for a manually verifiable demo.
HTMLInputElement
The identifier <input> element to arm. Must already
be attached to the DOM.
Promise<LoginResult | null>
cancelConditionalUI(): void;
Cancel a pending conditional UI ceremony armed by enableConditionalUI(), without arming a new one. Call this when the identifier input unmounts (route change, modal close) in an SPA, so the browser-level request doesn't stay pending indefinitely. Safe to call even when nothing is armed.
void
enableConditionalUI()/cancelConditionalUI()are not live-verified end to end, unlike every other method on this site. Every other code sample across this docs site was actually run against the real hosted API before being written down. This pair genuinely can't be — completing a conditional-UI ceremony requires a real saved passkey and the browser's own OS-level autofill dropdown, which no automated test can trigger or interact with. The signatures and behavior below are accurate (generated from the real source, same as everything else on this page), but the interactive round trip itself has only been exercised manually, not proven the same way the rest of this reference has. Treat this pair with that in mind.
checkPasskeyOfferEligibility(): Promise<boolean>;
Check whether to offer passkey creation right now. Call this after a
successful non-passkey login (e.g. from your own onAfterAuth
handler) and, if it resolves true, show your own "Add a passkey?"
prompt — on acceptance call addPasskey(), on dismissal call
dismissPasskeyOffer() so the offer doesn't reappear for 30 days.
Resolves false without any network call when this browser/device
doesn't support a platform passkey (Touch ID / Windows Hello /
Android biometric) — checked via
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().
Otherwise asks the server, which resolves false whenever the user
already has a passkey enrolled (item 7) or dismissed the offer within
the last 30 days.
Requires an active session — call after login()/register().
Promise<boolean>
dismissPasskeyOffer(): Promise<void>;
Record that the user dismissed the "add a passkey?" offer. Suppresses
checkPasskeyOfferEligibility() from resolving true again for 30
days. Call this when the user closes/declines your own offer prompt
— never automatically.
Requires an active session — call after login()/register().
Promise<void>
optional buttonClassName?: string;
CSS class to add to the button element
optional buttonStyle?: Partial<CSSStyleDeclaration>;
Inline styles to apply to the button element
optional label?: string;
Label for the button. Defaults to "Sign in with Passkey"
optional onError?: (err) => void;
Called when login fails, or when the flow needs UI mountButton can't render (identifier/confirm)
Error
void
optional onSuccess?: (result) => void;
Called when login succeeds
void