通行密钥

通行密钥(Passkeys)是一种安全、无需密码的身份验证方式,它利用加密密钥对,并得到 Web 浏览器中 WebAuthn 和 FIDO2 标准的支持。它通过唯一的密钥对替代传统密码:私钥存储在用户设备上,公钥则与网站共享。用户可通过生物识别、PIN 码或安全密钥登录,提供强大且防钓鱼的身份验证,无需依赖传统密码。

通行密钥插件的实现底层基于 SimpleWebAuthn

安装

将插件添加到认证配置中

要将 passkey 插件添加到认证配置中,您需要导入该插件并将其传递给认证实例的 plugins 选项。

选项

rpID: 您网站的唯一标识符。本地开发时可以使用 'localhost'

rpName: 您网站的可读标题

origin: 注册和认证应该发生的 URL。http://localhosthttp://localhost:PORT 也是有效的。不要包含尾部斜杠 /

authenticatorSelection: 允许自定义 WebAuthn 认证器选择标准。不指定则使用默认设置。

  • authenticatorAttachment: 指定认证器类型
    • platform: 认证器附加到平台(例如指纹读取器)
    • cross-platform: 认证器不附加到平台(例如安全密钥)
    • 默认值: not set(允许平台和跨平台认证器,优先选择平台认证器)
  • residentKey: 确定凭据存储行为。
    • required: 用户必须在认证器上存储凭据(最高安全性)
    • preferred: 鼓励凭据存储但不是强制性的
    • discouraged: 不需要凭据存储(最快体验)
    • 默认值: preferred
  • userVerification: 控制认证过程中的生物识别/PIN 验证:
    • required: 用户必须验证身份(最高安全性)
    • preferred: 鼓励验证但不是强制性的
    • discouraged: 不需要验证(最快体验)
    • 默认值: preferred
auth.ts
import { betterAuth } from "better-auth"
import { passkey } from "better-auth/plugins/passkey"

export const auth = betterAuth({
    plugins: [ 
        passkey(), 
    ], 
})

迁移数据库

运行迁移或生成模式,将必要的字段和表添加到数据库中。

npx @better-auth/cli migrate
npx @better-auth/cli generate

请参阅模式部分以手动添加字段。

添加客户端插件

auth-client.ts
import { createAuthClient } from "better-auth/client"
import { passkeyClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
    plugins: [ 
        passkeyClient() 
    ] 
})

使用方法

添加/注册通行密钥

要添加或注册通行密钥,请确保用户已通过身份验证,然后调用客户端提供的 passkey.addPasskey 函数。

POST
/passkey/add-passkey
const { data, error } = await authClient.passkey.addPasskey({    name: "example-passkey-name",    authenticatorAttachment: "cross-platform",});
属性描述类型
name?
用于标记正在注册的认证器账户的可选名称。如果未提供,将默认为用户的电子邮件地址或用户 ID
string
authenticatorAttachment?
您还可以指定要注册的认证器类型。默认行为允许同时使用平台和跨平台通行密钥
"platform" | "cross-platform"

使用通行密钥登录

要使用通行密钥登录,您可以使用 signIn.passkey 方法。这将提示用户使用其通行密钥登录。

POST
/sign-in/passkey
const { data, error } = await authClient.signIn.passkey({    email: "example@gmail.com", // required    autoFill: true,    callbackURL: "/dashboard",});
属性描述类型
email
要登录的用户的电子邮件。
string
autoFill?
浏览器自动填充,也称为条件 UI。了解更多:https://simplewebauthn.dev/docs/packages/browser#browser-autofill-aka-conditional-ui
boolean
callbackURL?
用户登录后重定向的 URL。
string

列出通行密钥

您可以通过调用 passkey.listUserPasskeys 来列出已认证用户的所有通行密钥:

GET
/passkey/list-user-passkeys
const { data: passkeys, error } = await authClient.passkey.listUserPasskeys();

删除通行密钥

您可以通过调用 passkey.delete 并提供通行密钥 ID 来删除通行密钥。

POST
/passkey/delete-passkey
const { data, error } = await authClient.passkey.deletePasskey({    id: "some-passkey-id", // required});
属性描述类型
id
要删除的通行密钥 ID。
string

更新通行密钥名称

POST
/passkey/update-passkey
const { data, error } = await authClient.passkey.updatePasskey({    id: "id of passkey", // required    name: "my-new-passkey-name", // required});
属性描述类型
id
要更新的通行密钥 ID。
string
name
通行密钥将更新为的新名称。
string

条件式 UI

该插件支持条件式 UI(Conditional UI),允许浏览器在用户已注册通行密钥时自动填充。

条件式 UI 需要满足两个要求:

更新输入字段

在输入字段中添加值为 webauthnautocomplete 属性。您可以在多个输入字段中添加此属性,但至少需要一个才能使条件式 UI 正常工作。

webauthn 值应作为 autocomplete 属性的最后一个条目。

<label for="name">用户名:</label>
<input type="text" name="name" autocomplete="username webauthn">
<label for="password">密码:</label>
<input type="password" name="password" autocomplete="current-password webauthn">

预加载通行密钥

当组件挂载时,您可以通过调用 authClient.signIn.passkey 方法并将 autoFill 选项设置为 true 来预加载用户的通行密钥。

为避免不必要的调用,我们还会添加检查以确认浏览器是否支持条件式 UI。

useEffect(() => {
   if (!PublicKeyCredential.isConditionalMediationAvailable ||
       !PublicKeyCredential.isConditionalMediationAvailable()) {
     return;
   }

  void authClient.signIn.passkey({ autoFill: true })
}, [])

根据浏览器的不同,会出现自动填充通行密钥的提示。如果用户有多个通行密钥,他们可以选择要使用的那个。

某些浏览器还要求用户先与输入字段交互,然后才会显示自动填充提示。

调试

要测试您的通行密钥实现,您可以使用模拟认证器。这样,您无需拥有物理设备即可测试注册和登录流程。

数据库表结构

该插件需要在数据库中创建一个新表来存储通行密钥数据。

表名:passkey

字段名称类型Key描述
idstring每个通行密钥的唯一标识符
namestring通行密钥的名称
publicKeystring-通行密钥的公钥
userIdstring用户的ID
credentialIDstring-注册凭证的唯一标识符
counternumber-通行密钥的计数器
deviceTypestring-用于注册通行密钥的设备类型
backedUpboolean-通行密钥是否已备份
transportsstring-用于注册通行密钥的传输方式
createdAtDate-通行密钥创建的时间
aaguidstring认证器的认证GUID,指示认证器的类型

配置选项

rpID:您网站的唯一标识符。对于本地开发环境,'localhost' 是可以接受的。

rpName:您网站的可读性标题。

origin:注册和认证应发生的URL。http://localhosthttp://localhost:端口号 也是有效的。请勿包含任何结尾的 /

authenticatorSelector:允许自定义 WebAuthn 认证器的选择标准。未指定时,平台认证器和跨平台认证器均被允许,且 residentKeyuserVerification 采用 preferred 设置。

aaguid:(可选)认证器证明 GUID。这是通行密钥提供者(设备或认证器类型)的唯一标识符,可用于识别注册或认证过程中使用的通行密钥设备类型。

On this page