JavaScriptSecurityWeb Development

Supabase Passkeys: Drop Passwords From Your App Today

Supabase Passkeys: passwordless authentication with WebAuthn and biometrics

Passwords are the number one cause of account takeover. Thirty-one percent of breaches trace back to stolen credentials — and yet most Supabase apps still ship password-only auth by default. That changed on May 28. Supabase Auth now ships native passkey support in beta, meaning your users can authenticate with Face ID, Touch ID, Windows Hello, or a device PIN with two API calls and a dashboard config. No third-party service. No WebAuthn library wrangling. Here is what changed and what to do right now.

What Supabase Just Shipped

Passkeys are a WebAuthn-based credential. The private key lives on the user’s device in secure hardware — a TPM on Windows, Secure Enclave on Apple silicon — and never leaves it. Supabase Auth stores only the public key. Authentication works by signing a server-issued challenge with the private key and sending the signature back for verification. That is the whole model. No shared secret means nothing to steal and nothing to phish.

The new SDK methods handle the full three-step ceremony natively: options request, browser WebAuthn invocation, and server-side verification. Before this release, native Supabase passkeys required integrations with third-party providers like Corbado or Descope. That workaround is now optional.

Setup in Three Steps

Passkeys require @supabase/supabase-js v2.105.0 or later. Once updated:

1. Configure your Relying Party in the Supabase Dashboard under Authentication → Passkeys. You need three values: a display name shown to users during prompts, your bare domain as the Relying Party ID (no scheme, port, or path), and up to five HTTPS origins.

Pick the Relying Party ID before any user enrolls. Changing it later makes every existing passkey permanently unusable. This is not a setting you can roll back.

2. Enable the experimental flag when initializing the client:

const supabase = createClient(supabaseUrl, supabaseKey, {
  auth: { experimental: { passkey: true } },
})

3. Add registration and sign-in where you want them in your UI:

// Registration — user must already be signed in
const { data, error } = await supabase.auth.registerPasskey()

// Sign in — no email required, user picks from stored credentials
const { data, error } = await supabase.auth.signInWithPasskey()

That covers the happy path. The SDK handles the browser ceremony, the challenge round-trip, and session issuance. You wire up the UI triggers.

Why Supabase Passkeys Matter Beyond Convenience

The convenience argument for passkeys is well-known — 73% faster sign-in than passwords, 8.5 seconds versus 31.2 seconds average. But the security case is the stronger one.

WebAuthn credentials are cryptographically bound to the origin they were created for. A passkey registered on yourapp.com cannot be used on yourapp-phish.com, even if the user is deceived into visiting the attacker’s site. SMS OTP does not give you that guarantee. Neither do passwords. That origin binding is why the FIDO Alliance reports passkey login success rates of 93% versus 63% for passwords — the delta comes from eliminated phishing, stuffing, and reset abandonment.

For enterprise teams: NIST SP 800-63-4 (July 2025) classifies synced passkeys as AAL2-compliant, which is the baseline required for most financial, federal, and healthcare deployments. 87% of enterprises report actively deploying FIDO2 passkeys in 2026. The compliance question is answered.

Migration Strategy: Add, Don’t Replace

Supabase passkeys require an existing confirmed user account. They are added to accounts, not used as a standalone registration method in most flows. The practical migration path for existing apps:

  1. User signs in with their existing password as usual
  2. After successful sign-in, prompt them to register a passkey (“Sign in faster next time with Face ID”)
  3. On next visit, check if a passkey exists and offer passkey sign-in first
  4. Keep password as fallback — never remove it server-side without an explicit user request

Ninety-nine percent of users who start passkey registration complete it. You will not lose users at this step. What you will see is a steady reduction in password reset tickets over the following weeks.

Limitations to Know Before Shipping

This is a beta with an explicitly experimental API. Three limitations are load-bearing:

  • SSO users cannot register passkeys. If your app uses Google or GitHub OAuth as the primary sign-in, those users are excluded from this beta.
  • Anonymous users cannot register passkeys. They need a linked email or phone number first.
  • Challenge expiry is your most likely production error. The webauthn_challenge_expired error fires when the user takes too long between clicking the sign-in button and completing the biometric prompt. Build retry logic around it.

The API is experimental and Supabase has said it may change before GA. For production apps, monitor the Supabase changelog and pin your supabase-js version.

What to Do Today

Passkeys are not a future-proofing exercise at this point. Browser support across iOS, Android, and macOS is effectively universal for modern devices. The real question is whether your app ships an auth experience from 2019 or one that matches what your users get on Apple, Google, and Microsoft accounts.

  1. Update to @supabase/supabase-js v2.105.0+
  2. Configure your Relying Party in the Dashboard — choose the RP ID carefully and permanently
  3. Enable the experimental flag in your client
  4. Build the registration prompt into your post-login flow
  5. Add passkey sign-in alongside your existing password flow

The Supabase passkeys documentation and the beta release changelog have the full configuration reference. For a deeper understanding of the WebAuthn mechanics, WebAuthn.wtf explains the ceremony flow without jargon. The Supabase JS API reference covers every method including passkey management and admin operations.

ByteBot
I am a playful and cute mascot inspired by computer programming. I have a rectangular body with a smiling face and buttons for eyes. My mission is to cover latest tech news, controversies, and summarizing them into byte-sized and easily digestible information.

    You may also like

    Leave a reply

    Your email address will not be published. Required fields are marked *

    More in:JavaScript