---
title: Passkey
description: 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](https://simplewebauthn.dev/) behind the scenes.

## Installation 

<Steps>
    <Step>
        ### 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 /

        ```ts title="auth.ts" 
        import { betterAuth } from "better-auth"
        import { passkey } from "better-auth/plugins"
        
        export const auth = betterAuth({
           
            plugins: [ // [!code highlight]
                passkey(), // [!code highlight]
            ], // [!code highlight]
        })
        ```
    </Step>
      <Step>
        ### Migrate the database

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

        <Tabs items={["migrate", "generate"]}>
            <Tab value="migrate">
            ```bash
            npx @better-auth/cli migrate
            ```
            </Tab>
            <Tab value="generate">
            ```bash
            npx @better-auth/cli generate
            ```
            </Tab>
        </Tabs>
        See the [Schema](#schema) section to add the fields manually.
    </Step>
    <Step>  
        ### Add the client plugin
        
         ```ts title="client.ts" 
            import { createAuthClient } from "better-auth/client"
            import { passkeyClient } from "better-auth/client/plugins"
            
            const client = createAuthClient({
                plugins: [ // [!code highlight]
                    passkeyClient() // [!code highlight]
                ] // [!code highlight]
            })
            ```
    </Step>
</Steps>


## 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.

```ts title="client.ts" 
    import { createAuthClient } from "better-auth/client"
    import { passkeyClient } from "better-auth/client/plugins"
    
    const client = createAuthClient({
        plugins: [ // [!code highlight]
            passkeyClient() // [!code highlight]
        ] // [!code highlight]
    })
// ---cut---
const data = await client.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](https://simplewebauthn.dev/docs/packages/browser#browser-autofill-aka-conditional-ui)

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

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

## Schema

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

Table Name: `passkey`

<DatabaseTable
    fields={[
        { 
            name: "id", 
            type: "string", 
            description: "Unique identifier for each passkey",
            isPrimaryKey: true
        },
        {
            name: "name",
            type: "string",
            description: "The name of the passkey",
            isOptional: true
        },
        { 
            name: "publicKey", 
            type: "string", 
            description: "The public key of the passkey",
        },
        { 
            name: "userId", 
            type: "string", 
            description: "The id of the user",
            isForeignKey: true
        },
        {
            name: "WebAuthnUserId",
            type: "string",
            description: "The user id for WebAuthn",
        },
        { 
            name: "counter", 
            type: "number", 
            description: "The counter of the passkey",
        },
        {
            name: "deviceType",
            type: "string",
            description: "The type of device used to register the passkey",
        },
        {
            name: "backedUp",
            type: "boolean",
            description: "Whether the passkey is backed up",
        },
        {
            name: "transports",
            type: "string",
            description: "The transports used to register the passkey",
        },
        { 
            name: "createdAt", 
            type: "Date", 
            description: "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 /.

