
Better Auth Passkey 插件演進全解從 1.6.0 到 1.7.3 的關鍵能力與安全加固【免費下載鏈接】better-authThe most comprehensive authentication framework項目地址: https://gitcode.com/GitHub_Trending/be/better-authPasskey 插件better-auth/passkey是 better-auth 倉庫中負責 WebAuthn 無密碼登錄的核心模塊覆蓋注冊、認證、憑據管理、會話創建與 OpenAPI 描述等完整鏈路。本文以 packages/passkey/CHANGELOG.md 為骨架結合倉庫源碼逐條剖析 1.6.01.7.3 期間的關鍵變更幫助你理解 Passkey 插件的功能邊界、配置項語義與底層實現并能在實際項目中正確選用這些能力。插件概覽一條完整的 WebAuthn 憑據管理鏈路在深入版本變更之前先明確 Passkey 插件在 better-auth 中的定位。它由服務端插件與客戶端插件兩部分組成服務端入口在 packages/passkey/src/index.ts客戶端入口在 packages/passkey/src/client.ts底層依賴simplewebauthn/server與simplewebauthn/browser見 packages/passkey/package.json。服務端注冊后共暴露 6 個端點見 index.ts端點方法作用/passkey/generate-register-optionsGET生成注冊選項challenge、rp、user、excludeCredentials 等/passkey/generate-authenticate-optionsGET生成認證選項challenge、allowCredentials 等/passkey/verify-registrationPOST校驗注冊響應并持久化 passkey/passkey/verify-authenticationPOST校驗認證響應并創建會話/passkey/list-user-passkeysGET列出當前用戶全部 passkey需登錄/passkey/delete-passkeyPOST刪除指定 passkey校驗資源歸屬/passkey/update-passkeyPOST重命名指定 passkey校驗資源歸屬服務端插件 ID 為passkey并暴露了version字段PACKAGE_VERSION客戶端插件同樣帶版本號。此外插件還從 authenticator-metadata.ts 導出commonAuthenticatorNames與getAuthenticatorName從 error-codes.ts 導出PASSKEY_ERROR_CODES。數據模型方面packages/passkey/src/schema.ts 定義了passkey表publicKey、userId引用 user 表并建立索引、credentialID索引、counter、deviceType、backedUp為必填字段name、transports、createdAt、aaguid為可選字段。任何版本變更最終都落在這張表與上述端點之上。1.7.0注冊即登錄 ——createSession可選配置CHANGELOG 中 1.7.0 與 1.7.0-rc.3 記載了本次 Minor Change為 passkey 注冊新增可選的createSession配置。啟用后注冊成功會直接完成登錄設置會話 Cookie并把 session 與 user 連同注冊的 passkey 一并返回。在源碼中該能力貫穿三層服務端請求體校驗verifyPasskeyRegistrationBodySchema新增createSession: z.boolean().optional()字段routes.ts服務端響應結構passkeyRegistrationResponseSchema在 Passkey 基礎上追加session與user兩個引用routes.ts客戶端透傳registerPasskey的選項新增createSession?: boolean發起校驗時條件性攜帶createSession: trueclient.ts 與 client.ts。底層實現位于 routes.ts當createSession為 true 時先通過internalAdapter.findUserById解析目標用戶隨后在runWithTransaction事務內完成 passkey 持久化與會話創建internalAdapter.createSession最后調用setSessionCookie寫入會話 Cookie并返回{ ...passkey, session, user }。創建會話時傳入了deferSecondaryStorageWrites: true將次要存儲寫入延遲到事務提交后保證主存儲與會話創建的一致性。這段實現同時揭示了注冊響應有兩種形態不帶createSession時只返回 passkey 對象帶createSession時返回 passkey session user。客戶端在收到verified.data.session后會通過$store.notify($sessionSignal)通知會話狀態變化client.ts前端無需再跳轉登錄頁即可保持登錄態。1.6.17挑戰值Challenge與儀式類型強綁定1.6.17 是一次安全加固對應 PR #9993注冊不能再使用為認證簽發的 challenge 完成反之亦然同時當目標用戶無法解析時注冊會被拒絕。從源碼結構看注冊與認證共用同一個簽名 Cookie默認名better-auth-passkey和同一張 verification 存儲行因此實現上用StoredChallengeValue給存儲的 challenge 打上了type標簽registration | authentication見 routes.ts生成注冊選項時寫入type: registrationroutes.ts生成認證選項時寫入type: authenticationroutes.ts兩個 verify 端點在校驗前都會先比對 ceremony 類型不匹配即拋CHALLENGE_NOT_FOUND注冊端 routes.ts認證端 routes.ts。同時注冊流程中如果存在會話而 challenge 里綁定的userData.id與當前會話用戶不一致會拋出YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEYroutes.ts注冊持久化時目標用戶為空也會被拒絕RESOLVED_USER_INVALID。這一改動防止了跨儀式重放 challenge、以及把 passkey 掛到錯誤用戶賬號下的攻擊面。1.6.15憑據友好名稱 —— AAGUID 解析與afterVerification命名1.6.15 解決了“passkey 列表里只顯示一串晦澀 ID”的問題。插件現在能從創建憑據的認證器 AAGUID 解析出友好名稱并新增兩個導出getAuthenticatorName(aaguid)把 AAGUID 解析為供應商名稱如 1Password、Google Password ManagercommonAuthenticatorNames內置的可擴展映射表。實現位于 packages/passkey/src/authenticator-metadata.ts。需要特別注意的是該映射表是“best-effort”且刻意保持精簡的并非權威清單隱私保護平臺如 Apple 設備在默認attestation: none流程下會上報全零 AAGUID00000000-0000-0000-0000-000000000000getAuthenticatorName對未知、空、全零值一律返回undefined避免誤標。文件注釋中建議需要完整覆蓋時參考社區維護的 AAGUID 數據源自行擴展映射。配套變更每個 passkey 行在注冊時持久化aaguid字段routes.tslistPasskeys返回后即可在管理界面渲染標簽registration.afterVerification回調現在可以返回name在客戶端未提供名稱時作為服務端默認標簽若客戶端提供了非空名稱則優先使用客戶端名稱純空白輸入視為未提供類型注釋見 types.ts實現見 routes.tspasskey 名稱在注冊與更新時均會trim處理注冊端 routes.ts更新端 routes.ts。典型渲染用法來自源碼注釋示例const label passkey.name || getAuthenticatorName(passkey.aaguid) || Passkey;1.6.7 與 1.6.19響應體與 OpenAPI 描述的一致性修復這兩個補丁都聚焦“聲明與實際返回一致”1.6.7/passkey/verify-authentication的 JSON 響應此前缺少user字段與端點聲明的 OpenAPI schema 及客戶端{ session, user }返回類型不一致。修復后服務端在驗證通過、創建會話后同時返回session與userroutes.ts保證調用方拿到的響應結構可預期。1.6.19修復 Better Auth 的 callback、session 與 passkey 路由中不合法的 OpenAPI 輸出使基于 OpenAPI 的客戶端代碼生成器可以正常消費 schema。注冊與認證選項端點在源碼中均帶完整的metadata.openapi描述如 routes.ts倉庫內 open-api.test.ts 即用于守護這類 schema 輸出。1.6.8exactOptionalPropertyTypes兼容性修復1.6.8 是一個典型的類型工程質量修復對應 issue #9212。此前 passkey 注冊端點的類型聲明中輸出了use: Middleware[] | undefined在開啟exactOptionalPropertyTypes: true的項目里不可賦值給EndpointOptions.use?: Middleware[]導致插件不再滿足BetterAuthPlugin約束進而引發其他無關插件的auth.api.*推斷丟失以及authClient.passkey.*推斷失效。修復后聲明輸出use: Middleware[]運行時行為不變。這個案例說明在嚴格可選屬性類型的 TS 工程中插件類型聲明的兼容性會級聯影響整個 auth 實例的推斷升級 passkey 插件版本即可消除這類級聯問題。1.6.10認證取消的友好處理1.6.10對應 PR #9429處理了 passkey 自動填充autofill登錄無法啟動時的體驗問題當瀏覽器環境不支持或用戶取消 WebAuthn 流程時客戶端不再拋出未處理的異常而是返回結構化的錯誤對象。在 client.ts 中signInPasskey用 try/catch 包裹startAuthentication捕獲到WebAuthnError時返回{ data: null, error: { code, message, status: 400, ... } }錯誤碼為AUTH_CANCELLEDmessage 取自 error-codes.ts 中的PASSKEY_ERROR_CODES.AUTH_CANCELLED。注冊側同樣對ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED已注冊過、ERROR_CEREMONY_ABORTED流程中止做了分類返回client.ts。1.6.0預認證注冊流程與 WebAuthn 擴展支持1.6.0 引入了兩項 Minor Change預認證注冊流程passkey-first。默認情況下注冊要求已登錄會話requireSession默認true見 types.ts此時注冊端點掛載freshSessionMiddlewareroutes.ts。關閉requireSession: false后插件會先嘗試從上下文取會話取不到則要求提供resolveUser回調由業務方根據請求上下文context查詢參數解析待注冊用戶routes.ts。這一能力支撐了“無密碼優先”的注冊體驗用戶還沒登錄即可先注冊 passkey再配合 1.7.0 的createSession一步完成登錄。相關錯誤碼包括SESSION_REQUIRED、RESOLVE_USER_REQUIRED、RESOLVED_USER_INVALID見 error-codes.ts。WebAuthn 擴展支持。注冊與認證選項都支持extensions可以是靜態對象也可以是接收{ ctx }的解析函數PasskeyExtensionsResolver見 types.ts。解析邏輯見 routes.ts客戶端在 client.ts 會把服務端擴展與調用方傳入的擴展合并后傳給瀏覽器 API。錯誤信息字符串修復1.6.0 同時修復了 passkey 客戶端返回“錯誤碼對象”而非“錯誤消息字符串”的問題配合 error-codes.ts 的集中定義前端可以直接消費可讀的中英文錯誤說明。配置速查Passkey 插件完整選項綜合 packages/passkey/src/types.ts 與 README完整配置項如下import { betterAuth } from better-auth; import { passkey } from better-auth/passkey; export const auth betterAuth({ plugins: [ passkey({ // 站點唯一標識本地開發可用 localhost默認值 rpID: example.com, // 站點可讀名稱默認 Better Auth rpName: My App, // 注冊/認證發生的 URLhttp://localhost 與帶端口形式也合法不要帶尾部 / // 不傳時由客戶端自行傳遞也可傳字符串數組 origin: https://example.com, // 自定義 authenticatorSelectionresidentKey/userVerification 默認 preferred authenticatorSelection: { authenticatorAttachment: platform, }, advanced: { // 存儲 WebAuthn challenge ID 的 Cookie 名默認 better-auth-passkey webAuthnChallengeCookie: better-auth-passkey, }, registration: { // 注冊是否需要已登錄會話默認 true requireSession: false, // requireSession 為 false 且無會話時解析待注冊用戶 resolveUser: async ({ ctx, context }) ({ id: user-id, name: userexample.com, displayName: User, }), // 注冊校驗成功后的鉤子可返回 userId改綁用戶或 name默認標簽 afterVerification: async ({ verification }) { return { name: My YubiKey }; }, // WebAuthn 擴展靜態對象或函數 extensions: { appid: https://example.com }, }, authentication: { afterVerification: async ({ ctx, verification }) {}, extensions: {}, }, // 自定義 passkey 表 schema可覆蓋字段類型與索引 schema: undefined, }), ], });客戶端插件一行接入即可獲得類型安全的調用import { createAuthClient } from better-auth/client; import { passkeyClient } from better-auth/passkey/client; export const authClient createAuthClient({ plugins: [passkeyClient()], }); // 使用示例 await authClient.signIn.passkey({ autoFill: true }); await authClient.passkey.addPasskey({ name: MacBook Touch ID, createSession: true }); await authClient.passkey.listUserPasskeys(); await authClient.passkey.deletePasskey({ id }); await authClient.passkey.updatePasskey({ id, name: New name });安裝方式packages/passkey/README.mdnpm install better-auth better-auth/passkey # 或 yarn add / pnpm add / bun add better-auth better-auth/passkey版本演進速覽版本變更類型核心內容1.7.0Minor注冊新增createSession注冊即登錄并返回 session/user1.6.17Patchchallenge 與儀式類型強綁定防跨儀式重放目標用戶不可解析時拒絕注冊1.6.15Patch導出getAuthenticatorName/commonAuthenticatorNamesafterVerification可返回名稱名稱 trim1.6.19Patch修復 callback/session/passkey 路由 OpenAPI 輸出1.6.10Patchautofill 認證無法啟動時返回結構化AUTH_CANCELLED錯誤1.6.8Patch修復exactOptionalPropertyTypes: true下插件類型約束破壞、推斷級聯丟失的問題1.6.7Patch/passkey/verify-authentication響應補上user字段與 schema 及客戶端返回類型一致1.6.0Minor預認證注冊流程requireSession: falseresolveUser、WebAuthn 擴展支持、插件 version 字段、客戶端錯誤信息字符串修復若需進一步驗證或擴展可深入閱讀倉庫中的 passkey.test.ts、client.test.ts 與 authenticator-metadata.test.ts這些測試覆蓋了注冊/認證全流程與 AAGUID 解析行為。【免費下載鏈接】better-authThe most comprehensive authentication framework項目地址: https://gitcode.com/GitHub_Trending/be/better-auth創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考