Skip to content
Migrating from NextAuth.js v4? Read our migration guide.
Getting Started
WebAuthn 🔬

WebAuthn (Passkeys)

⚠️

The WebAuthn / Passkeys provider is experimental and not recommended for production use.

The WebAuthn provider requires changes to all of the framework integration as well as any database adapter that plans to support it. Therefore, the WebAuthn provider is currently only supported in the following framework integration and database adapters. Support for more frameworks and adapters are coming soon.

  • next-auth@5.0.0-beta.8 or above
  • @auth/prisma-adapter@1.3.0 or above
  • node@20.0.0 or above

Install peer dependencies

npm install @simplewebauthn/server@9.0.3 @simplewebauthn/browser@9.0.1

The @simplewebauthn/browser peer dependency is only required for custom signin pages. If you’re using the Auth.js default pages, you can skip installing that peer dependency.

Apply the required schema Migrations

This is the raw SQL migration for PostgreSQL, for more details including example migrations for other databases, check out the updated Prisma schemas at the @auth/prisma-adapter docs.

In short, the Passkeys provider requires an additional table called Authenticator.

./migration/add-webauthn-authenticator-table.sql
-- CreateTable
CREATE TABLE "Authenticator" (
    "credentialID" TEXT NOT NULL,
    "userId" TEXT NOT NULL,
    "providerAccountId" TEXT NOT NULL,
    "credentialPublicKey" TEXT NOT NULL,
    "counter" INTEGER NOT NULL,
    "credentialDeviceType" TEXT NOT NULL,
    "credentialBackedUp" BOOLEAN NOT NULL,
    "transports" TEXT,
    PRIMARY KEY ("userId", "credentialID"),
    CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
 
 
-- CreateIndex
CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");

Update Auth.js Configuration

Add the Passkeys provider to your configuration. Also make sure you’re using a compatible database adapter.

./auth.ts
import Passkey from "next-auth/providers/passkey"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
 
const prisma = new PrismaClient()
 
export default {
  adapter: PrismaAdapter(prisma),
  providers: [Passkey],
  experimental: { enableWebAuthn: true },
}

If you’re using the built-in Auth.js pages, then you are good to go! Navigating to your /signin route should include a “Signin with Passkeys” button.

Custom Pages

If you’re using a custom signin page, you can leverage the next-auth signIn function to initiate WebAuthn registration and login flows with the following code.

💡

When using the WebAuthn signIn function, you’ll also need the @simplewebauth/browser peer dependency installed.

app/login/page.tsx
"use client"
 
import { useSession } from "next-auth/react"
import { signIn } from "next-auth/webauthn"
 
export default function Login() {
  const { data: session, update, status } = useSession()
 
  return (
    <div>
      {status === "authenticated" ? (
        <button onClick={() => signIn("passkey", { action: "register" })}>
          Register new Passkey
        </button>
      ) : status === "unauthenticated" ? (
        <button onClick={() => signIn("passkey")}>Sign in with Passkey</button>
      ) : null}
    </div>
  )
}
Auth.js © Balázs Orbán and Team - 2024