跳至內容
從 NextAuth.js v4 遷移?請閱讀 我們的遷移指南.
開始使用驗證WebAuthn 🔬

WebAuthn (通行金鑰)

⚠️

WebAuthn / 通行金鑰供應商為實驗性質,不建議用於正式環境。

WebAuthn 供應商需要對所有框架整合以及任何計畫支援它的資料庫轉接器進行變更。因此,WebAuthn 供應商目前僅在以下框架整合和資料庫轉接器中受到支援。對更多框架和轉接器的支援即將推出。

  • next-auth@5.0.0-beta.8 或更高版本
  • @auth/prisma-adapter@1.3.0 或更高版本
  • node@20.0.0 或更高版本

安裝對等相依性

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

僅當使用**自訂登入頁面**時,才需要 @simplewebauthn/browser 對等相依性。如果您正在使用 Auth.js 預設頁面,則可以跳過安裝該對等相依性。

套用必要的結構描述遷移

這是 PostgreSQL 的原始 SQL 遷移,有關更多詳細資訊,包括其他資料庫的範例遷移,請查看 @auth/prisma-adapter 文件中更新的 Prisma 結構描述。

簡而言之,通行金鑰供應商需要一個名為 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");

更新 Auth.js 設定

Passkeys 供應商新增至您的設定。另請確保您正在使用相容的資料庫轉接器。

./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 },
}

如果您正在使用內建的 Auth.js 頁面,那麼您就設定好了!導覽至您的 /signin 路由應該會包含「使用通行金鑰登入」按鈕。

自訂頁面

如果您正在使用自訂登入頁面,您可以使用 next-auth signIn 函式,透過以下程式碼啟動 WebAuthn 註冊和登入流程。

💡

使用 WebAuthn signIn 函式時,您也需要安裝 @simplewebauth/browser 對等相依性。

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 和團隊 -2024