繁體中文(香港)
  • webauthn
  • 密碼金鑰
  • 多因素驗證
  • nextjs

在 Next.js 中實現 WebAuthn:一個實踐指南

在 Next.js 中實現 WebAuthn 的實踐指南,附有即時程式碼範例。

Sijie
Sijie
Developer

歡迎回到我們的 WebAuthn 系列。在我們之前的文章中,我們已經講解了 WebAuthn 的基礎知識,以及 入門指南。如果你是新加入的讀者,歡迎查看這些基礎內容以便掌握進度。

今天,我們將捲起袖子,把理論付諸實踐。我們將利用 Next.js 的新功能 “Server Actions”。我們的目標是什麼呢?就是在 Next.js 應用中實現 WebAuthn,並讓自己準備好使用 WebAuthn。

在我們深入編碼之前,先讓你瞥一眼旅程的終點——一個功能完整的 示範網站。探索一下這個網站以查看 WebAuthn 的應用情況,並體驗一下你將會構建的內容。在這個示範網站中,你可以註冊新用戶並用剛註冊的密碼登入。

預覽

對於那些喜歡手中有地圖的人,我們也提供幫助!我們將討論的所有代碼都可以在一個公開的 GitHub 存儲庫 中找到。這個存儲庫是你的伴隨指南,提供我們實現的完整源代碼。

準備好踏上這段令人興奮的冒險了嗎?讓我們開始吧!

必要條件

開始之前,讓我們確保我們擁有一切所需:

  1. 一個 Next.js 專案:如果你還沒有設置 Next.js 專案,這裏有一個 快速指南 幫助你開始。
  2. 簡單 WebAuthn 庫:幾個軟件包來幫助減少將 WebAuthn 集成到網站所需的工作。使用你喜歡的包管理器安裝 @simplewebauthn/browser@simplewebauthn/server@simplewebauthn/typescript-types
  3. 會話存儲:我們將使用會話存儲來管理 WebAuthn 的挑戰。我們將使用 vercel 的 KV 來實現這一點。
  4. 用戶資料庫:一個用來存儲我們用戶已註冊密鑰的地方。為了簡單起見,我們也將使用 vercel 的 KV 來展示。

現在,手持工具和材料,我們準備開始構建。

使用 Vercel 的 KV 實現會話存儲

設置 KV 存儲

無論在生產環境還是本地開發中初始化 KV 存儲都很容易,請按照這個指南將 KV 存儲連接到你的專案並拉取環境值:https://vercel.com/docs/storage/vercel-kv/quickstart

實現會話管理功能

我們導出了 2 個功能:

  • getCurrentSession:使用 Next.js 的 cookie 幫助創建當前請求的會話,並返回該值。
  • updateCurrentSession:將數據保存到當前會話。

使用 Vercel 的 KV 實現用戶數據庫

與我們的會話實現類似,讓我們實現一個簡單的用戶數據庫。

我們創建了按郵件查找用戶的函數,並按郵件更新用戶數據。記住,這只是演示,在真實產品中,用戶數據通常保存在數據庫中。

準備 WebAuthn 功能

在我們繼續之前,讓我們看看註冊和認證流程的圖表:

如你所見,我們需要準備兩個功能:

  1. generateWebAuthnRegistrationOptions
  2. verifyWebAuthnRegistration

與註冊類似,登錄也需要兩個功能:

  1. generateWebAuthnLoginOptions
  2. verifyWebAuthnLogin

這裏是代碼:

構建網頁

我們已經完成了準備工作,讓我們構建頁面:

結論

恭喜你,透過實施 WebAuthn 在 Next.js 應用中的複雜過程初探!在總結時,重要的是要說明一些關鍵考慮因素,以將其部署到生產環境中。

生產部署的關鍵考慮

  1. 用戶標識符調整:在本教程中,我們使用電子郵件作為用戶標識符。然而,在生產情況下,你可能需要使用不同的標識符,例如**用戶ID用戶名**。
  2. 數據庫集成:雖然我們使用了 Vercel 的 KV 作為會話和用戶數據管理的簡單演示,但真實的應用應該集成一個更強大的數據庫系統(如 PostgreSQL、MongoDB 等)。
  3. 自定義 WebAuthn 選項:我們探討的 WebAuthn 選項是起始點。根據你的應用需求和安全政策,你可能需要調整這些設置。請參閱 WebAuthn 文檔Simple WebAuthn 庫的文檔 以獲得關於自定義這些選項以滿足特定需求的指導。

感謝你參加我們這次的教育冒險。即使在這個最小化的範例中,集成 WebAuthn 也不是一件簡單的事情,還有另一個選擇,嘗試 WebAuthn 在 Logto 的 MFA 中的應用: