Skip to main content
General
Authentication

Passkeys

Configure passwordless passkey sign-in and account-managed WebAuthn credentials.

Open MarkdownFull AI corpusFeedback

Passkeys let users authenticate with the same biometric, device PIN or external security key they use to unlock a trusted authenticator. The starter kit integrates Better Auth's passkey plugin with registration, sign-in and account-management UI.

Included flow

  • Sign in with passkey appears below the configured OAuth providers.
  • Signed-in users manage passkeys from Dashboard → Settings → Security.
  • A user can register multiple passkeys, give each one a recognizable name, rename it later and remove it with confirmation.
  • Registration and authentication require WebAuthn user verification.
  • Browser ceremony errors are mapped to actionable messages instead of a generic authentication failure.

The feature is enabled by default:

config/auth.config.ts
export const authConfig = {
  // ... other settings
  enablePasskeys: true
};

Setting enablePasskeys to false removes the sign-in and account-management UI and stops registering the passkey server plugin. It therefore disables the corresponding Better Auth endpoints as well.

Database migration

Passkey metadata is stored in the passkey table. The table records the public credential, counter, authenticator information, optional display name and the owning user. Private key material never leaves the user's authenticator.

New downloads include the ORM-specific migration. Existing projects must apply it before deploying the passkey-enabled application:

Terminal
npm run db:migrate

No new environment variable is required.

Require user verification

The server registers the plugin with userVerification: 'required' and checks the authentication result before creating a session:

lib/auth/index.ts
passkey({
  authenticatorSelection: {
    userVerification: 'required'
  },
  authentication: {
    afterVerification: async ({ verification }) => {
      if (!verification.authenticationInfo.userVerified) {
        throw new APIError('UNAUTHORIZED', {
          code: 'PASSKEY_USER_VERIFICATION_REQUIRED',
          message:
            'Verify your identity with a PIN or biometric to use this passkey.'
        });
      }
    }
  }
});

This protects against accepting a ceremony that proves possession of an authenticator without proving the person using it. Keep both the WebAuthn option and the server-side result check when adapting the integration.

Passkeys and TOTP

A user-verified passkey is treated as the complete passwordless sign-in method. It does not redirect to a second TOTP challenge. Password sign-in still follows the user's configured Better Auth two-factor flow.

This distinction avoids asking for two independent possession checks during a single passkey ceremony while preserving TOTP for password-based authentication. If your product requires a separate step-up challenge for a sensitive action, implement and test that policy around the action instead of assuming every authentication method passes through the password hook.

HTTPS and relying-party scope

WebAuthn requires a secure context in production. Browsers allow localhost during development, but deployed passkeys are scoped to their relying party and origin. Test registration and authentication on the same production domain your customers will use.

Changing domains later can prevent existing credentials from matching the new relying party. Plan custom domains and authentication subdomains before relying on passkeys as the only recovery path.

Test the complete ceremony

The starter kits include a Playwright test backed by Chromium's virtual WebAuthn authenticator. It verifies registration, naming, rename, sign-out, passwordless sign-in and deletion. It also switches user verification off and confirms the server rejects the ceremony before retrying with verification enabled.

Run the focused test with:

Terminal
npm run with-dev-env -- playwright test tests/e2e/passkeys.spec.ts --project=chromium

Keep a normal password or recovery strategy available while evaluating browser, platform-authenticator and security-key support for your customer base.