← 文章与指南

为 Next.js App Router 应用接入 Passkey 登录

配置 Passkey 规则、接入 Next.js 服务端处理函数,并验证托管登录流程。

你可以为 Next.js 应用提供 Passkey 登录,而无需在应用里实现 WebAuthn 认证流程。Sudomimus 托管 Passkey 验证。Next.js 服务端负责发起 Connect 登录、处理回调,并在服务端保存会话。

应用登录产品页展示了用户看到的登录体验。

本文使用官方 @sudomimus/nextjs 集成和 Next.js App Router,适用于用户通过浏览器登录的应用。如果你的应用已有标准 OIDC 库,先看 OIDC 与 Connect 如何选择。

1. 配置应用

在 With 门户创建组织和应用。保存 applicationAnchor 与 client-auth 私钥。私钥只显示一次,必须存放在受保护的服务端环境中。

测试登录前,配置以下规则:

  1. **第一层:**添加 PASSKEY_USERNAMELESS,让登录页在邮箱输入框之前显示 Passkey 按钮;添加 PASSKEY_REASONED,让用户输入邮箱后选择 Passkey;也可以两者都添加。每条规则的 payload 都是空对象 {}。
  2. **第二层:**添加允许目标账户登录的 realize 规则。例如,可用 EMAIL 规则允许测试邮箱。仅配置第一层不会放行账户。
  3. **第三层:**添加 CALLBACK 返回规则,允许 Next.js 回调 URL 的主机名,并在 SDK 配置中填写准确的回调 URL。

独立 Passkey 按钮对应的第一层规则如下:

第一层规则JSON
{
"method": "PASSKEY_USERNAMELESS",
"payload": {}
}

新应用初始为 DRAFT。规则和回调准备好后,启用应用。用户还需要事先在 Sudomimus 注册 Passkey;应用规则只控制登录入口,不会替用户注册凭证。

2. 接入服务端路由

安装 @sudomimus/nextjs,创建服务端专用模块。按 Next.js SDK 指南配置 Connect options 和共享、持久的 WebAuthStore。不要把 client-auth 私钥或待完成登录状态放进 Client Component。

src/lib/sudomimus.tsTypeScript
import { createNextHandlers } from "@sudomimus/nextjs";
export const {
start,
callback,
logout,
current,
currentFromCookieHeader,
} = createNextHandlers(options);

从 App Router 的路由文件导出处理函数:

app/api/login/route.tsTypeScript
export { start as POST } from "@/lib/sudomimus";
// app/auth/callback/route.ts
export { callback as GET } from "@/lib/sudomimus";
// app/api/logout/route.ts
export { logout as POST } from "@/lib/sudomimus";

登录和登出使用 POST。SDK 会根据回调来源校验请求的 Origin。保留 CSRF 防护,不要把这些处理函数改成 GET 链接。

3. 在服务端读取会话

在 Route Handler 中调用 current(request)。在 Server Component 中,将请求的 cookie header 传给 currentFromCookieHeader。页面只渲染所需的用户资料。不要把返回的令牌传给 Client Component、浏览器存储或日志。

浏览器在 Sudomimus 页面完成 Passkey 验证,然后返回应用回调。你的应用无需直接调用浏览器 WebAuthn API。如果两种 Passkey 规则都已启用,用户可以点击独立按钮,也可以先输入邮箱;两者使用同一份已注册的凭证。

4. 验证接入边界

测试已注册的 Passkey、没有 Passkey 的用户、取消浏览器验证,以及未经允许的回调主机名。即使 Passkey 验证成功,如果没有匹配的第二层规则,应用仍应拒绝登录。最后测试登出和重新登录。

规则细节见 Passkey 认证规则。完整 Connect 生命周期见首次登录教程。