Skip to Content
Delmare Digital

Passkeys

Add passkey sign-in to the admin login, and use the standalone sign-in, registration and management components.

Passkeys come from Better Auth's @better-auth/passkey plugin, an optional peer. Install it and add passkey() to your Better Auth plugins.

npm i @better-auth/passkey

Passkeys on the admin login

The default login view does not import @better-auth/passkey, so projects without it still build. To offer passkey sign-in on the admin login, point the login view at the passkey-enabled wrapper. It runs the same sign-in method detection as the default and injects a passkey-capable client:

src/payload.config.ts
createBetterAuthPlugin({
  createAuth,
  admin: {
    loginViewComponent:
      '@delmaredigital/payload-better-auth/components/login-passkey#LoginViewWrapperWithPasskey',
    login: { enablePasskey: true },
  },
})

enablePasskey accepts true, false or 'auto' (show the button if the passkey plugin is detected). The effective default is 'auto': the button appears when the passkey plugin is detected. Use the passkey-enabled wrapper above to supply its client.

If you render LoginView yourself, pass an authClient built with passkeyClient(). Without one, the passkey button shows a message explaining what is missing instead of failing.

Standalone sign-in button

import { PasskeySignInButton } from '@delmaredigital/payload-better-auth/components/passkey'

<PasskeySignInButton
  onSuccess={(user) => router.push('/dashboard')}
  onError={(error) => setError(error)}
/>

Registration and management

// Registration button
import { PasskeyRegisterButton } from '@delmaredigital/payload-better-auth/components/passkey'
<PasskeyRegisterButton passkeyName="My MacBook" onSuccess={refetch} />

// Full management UI
import { PasskeysManagementClient } from '@delmaredigital/payload-better-auth/components/passkey'
<PasskeysManagementClient title="Manage Passkeys" />

The buttons also accept label, loadingLabel and authClient.

Or use the auth client directly (requires passkeyClient() in your client plugins):

await authClient.passkey.addPasskey({ name: 'My Device' })
await authClient.passkey.listUserPasskeys()
await authClient.passkey.deletePasskey({ id: passkeyId })

In the admin, users manage their passkeys from their own account; see Security management.

Edit this page on GitHub

On this page