Passkey MFA is supported in web environments only. TOTP and SMS remain available on all platforms. Enrollment and verification each run a single browser prompt—there is no code to enter.
How passkeys differ from TOTP and SMS
- No code entry: enrollment and verification are single WebAuthn ceremonies driven by
navigator.credentials, not a 6-digit code. - Single-call SDK surface:
enrollPasskeyandverifyPasskeyrun initiate → browser prompt → submit in one call, so they don’t use the sharedinitiate/submitMFA hooks. - Multiple credentials: a user can register more than one passkey (for example, one per device). Enrolled passkeys are a list, unlike the single TOTP or SMS registration.
- User gesture required:
verifyPasskeymust be called from a user gesture (a click). Browsers block the credential prompt otherwise.
Project configuration
Enable passkey for your project in the CDP Portal. Passkey has two settings: the method toggle itself, and User verification. Unlike TOTP and SMS, the passkey toggle is enforced server-side. Enrollment fails while passkey is off for the project, even from the hooks or the Core SDK. Users who already enrolled can still verify with their passkeys if you later turn the method off.Allowed origins
Every passkey ceremony is scoped to the origin it runs on:- Passkey requests must carry an
Originheader, and that origin must be one of your project’s configured CORS origins. A request from an unlisted origin is rejected withOrigin is not an allowed origin for this project. - The WebAuthn relying party ID is that origin’s exact host, not its registrable domain. An origin of
https://app.example.comproduces credentials scoped toapp.example.com. - There is nothing to configure and nothing to prove by DNS. The relying party ID is derived per ceremony and recorded on each credential, where you can read it back as
PasskeySummary.rpId.
User verification
The optionaluserVerification setting controls whether the authenticator must verify the user (for example, with biometrics or a PIN). It appears in the Portal as a User verification select once passkey is on:
preferred(default): request user verification, but allow the ceremony to proceed without it.required: fail the ceremony if the authenticator cannot verify the user.discouraged: skip user verification where possible.
Enrollment
Passkey enrollment runs the full WebAuthn registration ceremony in a single call. Gate the UI on passkey support so it only appears where the browser supports WebAuthn.- React hooks
- Core SDK
useIsPasskeySupported is a query hook: it runs the check on mount and exposes the answer on data, which is undefined until the check resolves. enrollPasskey never rejects, so an event handler needs no catch; read the outcome from status and error.enrollPasskeyAsync instead when you need the enrolled user inline. It resolves with { user } and rejects on failure.name is a human-friendly label (for example, the device or browser) surfaced when listing enrolled passkeys.
Verification
Passkey verification also runs in a single call. Call it from a user gesture.- React hooks
- Core SDK
Use
verifyPasskeyAsync when the next step depends on the result. The non-throwing verifyPasskey resolves even when the ceremony fails, so retrying the original operation after it would retry on a cancelled prompt too.Managing enrolled passkeys
A user may enroll up to 20 passkeys, so list and delete them by credential ID.- React hooks
- Core SDK
useListPasskeys fetches on mount and keys the query on the signed-in user, so enrolling or deleting a passkey does not refresh it. Call refetch after a mutation you want reflected on screen.Deleting one of several passkeys always succeeds. Deleting the user’s only passkey is rejected when passkey is their last enrolled MFA method and your project requires MFA verification on login. Enroll another method first.
A maximum of 20 passkeys may be enrolled. Delete one before enrolling another.
Each PasskeySummary describes an enrolled passkey:
Checking passkey enrollment
Passkey is included in the standard MFA enrollment helpers.- React Hooks
- Vanilla JS
Pre-built UI
The@coinbase/cdp-react EnrollMfa and VerifyMfa components render passkey alongside TOTP and SMS when the project has passkey enabled and the browser supports it. Passkey shows a single button (no code input); TOTP and SMS are unchanged. No extra wiring is required beyond the standard components:
SDK reference
Passkey adds a web-only surface to the CDP frontend SDKs.Hooks (@coinbase/cdp-hooks)
Action hooks expose a non-throwing action for event handlers, an *Async variant that resolves with the result and rejects on failure, and the tracked data, error, status, and reset. Query hooks run on mount and expose data, error, status, refetch, and reset.
Core functions (@coinbase/cdp-core)
enrollPasskey accepts an optional name and idempotencyKey; verifyPasskey accepts an optional idempotencyKey.
For full API details, see the cdp-hooks reference, cdp-core reference, and cdp-react reference.
Browser and platform support
- Passkeys work in web browsers that implement WebAuthn (
navigator.credentials). UseisPasskeySupported()to detect availability at runtime; it resolves tofalsewhen the browser has no usable authenticator. - The passkey surface ships only in the web build of
@coinbase/cdp-core. React Native builds resolve the native entry point, which exports none of these functions, so offer TOTP or SMS there. - Authenticator support (Face ID, Touch ID, Windows Hello, security keys) depends on the user’s device and browser.
Error handling
The Core SDK passkey functions throw anMfaError carrying a code. Three codes matter for passkey:
error rather than throwing, except through the *Async variants.
What to read next
Enrollment
Enroll users across TOTP, SMS, and passkey
Prompt Handling
Handle MFA prompts for sensitive operations
Protected Operations
Learn what triggers MFA verification
Best Practices
Security recommendations and UX considerations