threshold1

Passkey Management

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.

Methods

addPasskey()

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.

Parameters

options?
email?

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.

externalUserId?

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.

Returns

Promise<{ createdAt: string; credentialId: string; deviceHint: string | null; }>


listPasskeys()

listPasskeys(): Promise<object[]>;

List all passkeys registered for the current user. Requires an active session.

Returns

Promise<object[]>


removePasskey()

removePasskey(credentialId): Promise<void>;

Remove a passkey by credential ID. Requires an active session. Only removes passkeys owned by the current user.

Parameters

credentialId

string

The credential ID to remove (from listPasskeys())

Returns

Promise<void>


mountButton()

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.

Parameters

container

HTMLElement

A DOM element to render the button into

options?

MountButtonOptions

Optional label, callbacks, and className

Returns

Promise<void>


enableConditionalUI()

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.

Parameters

input

HTMLInputElement

The identifier <input> element to arm. Must already be attached to the DOM.

Returns

Promise<LoginResult | null>


cancelConditionalUI()

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.

Returns

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()

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().

Returns

Promise<boolean>


dismissPasskeyOffer()

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().

Returns

Promise<void>

Types

MountButtonOptions

Properties

buttonClassName?

optional buttonClassName?: string;

CSS class to add to the button element


buttonStyle?

optional buttonStyle?: Partial<CSSStyleDeclaration>;

Inline styles to apply to the button element


label?

optional label?: string;

Label for the button. Defaults to "Sign in with Passkey"


onError?

optional onError?: (err) => void;

Called when login fails, or when the flow needs UI mountButton can't render (identifier/confirm)

Parameters

err

Error

Returns

void


onSuccess?

optional onSuccess?: (result) => void;

Called when login succeeds

Parameters

result

LoginResult

Returns

void