Docs

Passkey

Passkeys are a secure, passwordless authentication method using cryptographic key pairs, supported by WebAuthn and FIDO2 standards in web browsers. They replace passwords with unique key pairs: a private key stored on the user’s device and a public key shared with the website. Users can log in using biometrics, PINs, or security keys, providing strong, phishing-resistant authentication without traditional passwords.

The passkey plugin implementation is powered by simple-web-authn behind the scenes.

Installation

Add the plugin to your auth config

To add the passkey plugin to your auth config, you need to import the plugin and pass it to the plugins option of the auth instance.

Options

rpID: A unique identifier for your website. 'localhost' is okay for local dev

rpName: Human-readable title for your website

origin: The URL at which registrations and authentications should occur. 'http://localhost' and 'http://localhost:PORT' are also valid.Do NOT include any trailing /

auth.ts
import { betterAuth } from "better-auth"
import { passkey } from "better-auth/plugins"
 
export const auth = betterAuth({
   
    plugins: [ 
        passkey(), 
    ], 
})

Migrate the database

Run the migration or generate the schema to add the necessary fields and tables to the database.

npx @better-auth/cli migrate

See the Schema section to add the fields manually.

Add the client plugin

auth-client.ts
   import { createAuthClient } from "better-auth/client"
   import { passkeyClient } from "better-auth/client/plugins"
   
   const authClient =  createAuthClient({
       plugins: [ 
           passkeyClient() 
       ] 
   })

Usage

Add/Register a passkey

To add or register a passkey make sure a user is authenticated and then call the passkey.addPasskey function provided by the client.

auth-client.ts
    import { createAuthClient } from "better-auth/client"
    import { passkeyClient } from "better-auth/client/plugins"
    
    const authClient =  createAuthClient({
        plugins: [ 
            passkeyClient() 
        ] 
    })
// ---cut---
const data = await authClient.passkey.addPasskey()

This will prompt the user to register a passkey. And it'll add the passkey to the user's account.

Signin with a passkey

To signin with a passkey you can use the passkeySignIn method. This will prompt the user to sign in with their passkey.

Signin method accepts:

autoFill: Browser autofill, a.k.a. Conditional UI. read more

callbackURL: The URL to redirect to after the user has signed in. (optional)

auth-client.ts
    import { createAuthClient } from "better-auth/client"
    import { passkeyClient } from "better-auth/client/plugins"
    
    const authClient =  createAuthClient({
        plugins: [ 
            passkeyClient() 
        ] 
    })
// ---cut---
const data = await authClient.signIn.passkey()

Schema

The plugin require a new table in the database to store passkey data.

Table Name: passkey

Field NameTypeKeyDescription
id
string
Unique identifier for each passkey
name
string
The name of the passkey
publicKey
string
-The public key of the passkey
userId
string
The id of the user
webauthnUserID
string
-The user id for WebAuthn
counter
number
-The counter of the passkey
deviceType
string
-The type of device used to register the passkey
backedUp
boolean
-Whether the passkey is backed up
transports
string
-The transports used to register the passkey
createdAt
Date
-The time when the passkey was created

Options

rpID: A unique identifier for your website. 'localhost' is okay for local dev.

rpName: Human-readable title for your website.

origin: The URL at which registrations and authentications should occur. 'http://localhost' and 'http://localhost:PORT' are also valid. Do NOT include any trailing /.

On this page