Passkey
通行密钥是一种安全的、无密码认证方法,使用加密密钥对,由 WebAuthn 和 FIDO2 标准支持,在 Web 浏览器中可用。它们用唯一的密钥对替换密码:私钥存储在用户设备上,公钥与网站共享。用户可以使用生物识别、PIN 或安全密钥登录,提供强大的、抗钓鱼的认证,而无需传统密码。
通行密钥插件的实现由 SimpleWebAuthn 在幕后提供支持。
安装
将插件添加到您的认证配置
要将通行密钥插件添加到您的认证配置中,您需要导入插件并将其传递到认证实例的 plugins 选项。
选项
rpID:您的网站的唯一标识符。对于本地开发,'localhost' 是可以的
rpName:您的网站的人类可读标题
origin:注册和认证应发生的 URL。http://localhost 和 http://localhost:PORT 也是有效的。不要包含任何尾随的 /
authenticatorSelection:允许自定义 WebAuthn 认证器选择标准。如果未指定,则使用默认设置。
authenticatorAttachment:指定认证器类型platform:认证器附加到平台(例如,指纹阅读器)cross-platform:认证器未附加到平台(例如,安全密钥)- 默认:
not set(允许平台和跨平台两种,优先平台)
residentKey:确定凭据存储行为。required:用户必须在认证器上存储凭据(最高安全性)preferred:鼓励凭据存储但非强制discouraged:无需凭据存储(最快体验)- 默认:
preferred
userVerification:控制认证期间的生物识别/PIN 验证:required:用户必须验证身份(最高安全性)preferred:鼓励验证但非强制discouraged:无需验证(最快体验)- 默认:
preferred
import { betterAuth } from "better-auth"
import { passkey } from "better-auth/plugins/passkey"
export const auth = betterAuth({
plugins: [
passkey(),
],
})迁移数据库
运行迁移或生成架构,以向数据库添加必要的字段和表。
npx @better-auth/cli migratenpx @better-auth/cli generate请参阅 Schema 部分以手动添加字段。
添加客户端插件
import { createAuthClient } from "better-auth/client"
import { passkeyClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
passkeyClient()
]
})使用方法
添加/注册通行密钥
要添加或注册通行密钥,请确保用户已认证,然后调用客户端提供的 passkey.addPasskey 函数。
const { data, error } = await authClient.passkey.addPasskey({ name: "example-passkey-name", authenticatorAttachment: "cross-platform",});| Prop | Description | Type |
|---|---|---|
name? | 用于标记正在注册的认证器账户的可选名称。如果未提供,将默认使用用户的电子邮件地址或用户 ID | string |
authenticatorAttachment? | 您还可以指定要注册的认证器类型。默认行为允许平台和跨平台通行密钥 | "platform" | "cross-platform" |
使用通行密钥登录
要使用通行密钥登录,您可以使用 signIn.passkey 方法。这将提示用户使用其通行密钥登录。
const { data, error } = await authClient.signIn.passkey({ email: "example@gmail.com", // required autoFill: true,});| Prop | Description | Type |
|---|---|---|
email | 要登录的用户电子邮件。 | string |
autoFill? | 浏览器自动填充,即条件 UI。阅读更多:https://simplewebauthn.dev/docs/packages/browser#browser-autofill-aka-conditional-ui | boolean |
示例用法
// 带有认证后重定向
await authClient.signIn.passkey({
email: "user@example.com",
autoFill: true,
fetchOptions: {
onSuccess(context) {
// 认证成功后重定向到仪表板
window.location.href = "/dashboard";
},
onError(context) {
// 处理认证错误
console.error("Authentication failed:", context.error.message);
}
}
});列出通行密钥
您可以通过调用 passkey.listUserPasskeys 来列出认证用户的所有通行密钥:
const { data: passkeys, error } = await authClient.passkey.listUserPasskeys();删除通行密钥
您可以通过调用 passkey.delete 并提供通行密钥 ID 来删除通行密钥。
const { data, error } = await authClient.passkey.deletePasskey({ id: "some-passkey-id", // required});| Prop | Description | Type |
|---|---|---|
id | 要删除的通行密钥 ID。 | string |
更新通行密钥名称
const { data, error } = await authClient.passkey.updatePasskey({ id: "id of passkey", // required name: "my-new-passkey-name", // required});| Prop | Description | Type |
|---|---|---|
id | 要更新的通行密钥 ID。 | string |
name | 将通行密钥更新为的新名称。 | string |
条件 UI
该插件支持条件 UI,这允许浏览器如果用户已注册通行密钥,则自动填充通行密钥。
条件 UI 工作的两个要求:
更新输入字段
将 autocomplete 属性添加到您的输入字段,并将其值设置为 webauthn。您可以向多个输入字段添加此属性,但至少需要一个以使条件 UI 工作。
webauthn 值还应是 autocomplete 属性的最后一个条目。
<label for="name">Username:</label>
<input type="text" name="name" autocomplete="username webauthn">
<label for="password">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 })
}, [])根据浏览器不同,将出现一个提示来自动填充通行密钥。如果用户有多个通行密钥,他们可以选择要使用的那个。
某些浏览器还要求用户首先与输入字段交互,然后自动填充提示才会出现。
调试
要测试您的通行密钥实现,您可以使用 emulated authenticators。这样,您可以测试注册和登录过程,而无需拥有物理设备。
架构
该插件需要在数据库中创建一个新表来存储通行密钥数据。
表名:passkey
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | 每个通行密钥的唯一标识符 | |
| name | string | 通行密钥的名称 | |
| publicKey | string | - | 通行密钥的公钥 |
| userId | string | 用户的 ID | |
| credentialID | string | - | 已注册凭据的唯一标识符 |
| counter | number | - | 通行密钥的计数器 |
| deviceType | string | - | 用于注册通行密钥的设备类型 |
| backedUp | boolean | - | 通行密钥是否已备份 |
| transports | string | - | 用于注册通行密钥的传输方式 |
| createdAt | Date | - | 通行密钥创建的时间 |
| aaguid | string | 认证器的证明 GUID,表示认证器类型 |
选项
rpID:您的网站的唯一标识符。对于本地开发,'localhost' 是可以的。
rpName:您的网站的人类可读标题。
origin:注册和认证应发生的 URL。http://localhost 和 http://localhost:PORT 也是有效的。请勿包含任何尾随 /。
authenticatorSelection:允许自定义 WebAuthn 认证器选择标准。如果未指定,则允许平台和跨平台认证器,并为 residentKey 和 userVerification 使用 preferred 设置。
aaguid:(可选)认证器证明 GUID。这是通行密钥提供程序(设备或认证器类型)的唯一标识符,可用于识别注册或认证期间使用的通行密钥设备类型。