关于 clerk-auth
面向维护 JavaScript 和 Next.js 应用中 Clerk 身份验证的开发者,提供参考指南。重点涵盖破坏性变更、安全用法、测试及常见错误修复。
主要功能
- 01Clerk API 与 SDK 迁移说明
- 02Next.js 异步 auth() 用法
- 03令牌安全与 JWT 大小建议
- 04Clerk 测试和会话令牌示例
- 0511 个已记录问题的修复方案
适用场景
- 01将应用升级到新版 Clerk API
- 02核对 Next.js v6 身份验证变更
- 03预防 CSRF 和 JWT 超限问题
- 04配置 Clerk 身份验证测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill clerk-auth安装后在 Claude Code 中输入/clerk-auth确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.claude-plugin/plugin.jsonassets/example-template.txtreferences/common-errors.mdexample-reference.mdjwt-claims-guide.mdtesting-guide.mdscripts/example-script.shgenerate-session-token.jstemplates/cloudflare/worker-auth.tswrangler.jsonctemplates/env-examples/.dev.vars.example.env.local.example.env.local.vite.exampletemplates/jwt/advanced-template.jsonbasic-template.jsongrafbase-template.jsonsupabase-template.jsontemplates/nextjs/app-layout.tsxmiddleware.tsserver-component-example.tsxtemplates/react/App.tsxmain.tsxtemplates/typescript/custom-jwt-types.d.tstemplates/vite/package.json详细介绍
Clerk Auth - 重大变更与错误预防指南
软件包版本:@clerk/[email protected]、@clerk/[email protected]、@clerk/[email protected]、@clerk/[email protected] 重大变更:2025 年 11 月 - API 版本 2025-11-10;2024 年 10 月 - Next.js v6 异步 auth() 上次更新:2025-11-22
v6.35.x 与 API 2025-11-10 的新变化(2025 年 11 月)
1. API 版本 2025-11-10(2025 年 11 月 10 日)- 重大变更 ⚠️
影响范围: 使用 Clerk Billing/Commerce API 的应用
关键变更:
-
端点 URL:
/commerce/→/billing/(30 多个端点)GET /v1/commerce/plans → GET /v1/billing/plans GET /v1/commerce/statements → GET /v1/billing/statements POST /v1/me/commerce/checkouts → POST /v1/me/billing/checkouts -
字段术语:
payment_source→payment_method// OLD (deprecated) { payment_source_id: "...", payment_source: {...} } // NEW (required) { payment_method_id: "...", payment_method: {...} } -
已移除的字段: Plans 响应不再包含:
amount、amount_formatted(改用fee.amount)currency、currency_symbol(改用 fee 对象)payer_type(改用for_payer_type)annual_monthly_amount、annual_amount
-
已移除的端点:
- Invoices 端点(改用 statements)
- Products 端点
-
空值处理: 明确规定:
null表示“不存在”,省略则表示“不声明是否存在”
迁移: 将 SDK 更新到 v6.35.0+,该版本支持 API 版本 2025-11-10。
官方指南: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10
2. Next.js v6 异步 auth()(2024 年 10 月)- 重大变更 ⚠️
影响范围: 所有使用 auth() 的 Next.js 服务端组件
// ❌ OLD (v5 - synchronous)
const { userId } = auth()
// ✅ NEW (v6 - asynchronous)
const { userId } = await auth()
同样受影响: auth.protect() 在中间件中现在是异步的
// ❌ OLD (v5)
auth.protect()
// ✅ NEW (v6)
await auth.protect()
兼容性: 支持 Next.js 15、16。默认使用静态渲染。
3. 自定义 OAuth 的 PKCE 支持(2025 年 11 月 12 日)
自定义 OIDC 提供商和社交连接现在支持 PKCE(Proof Key for Code Exchange),可为原生/移动应用提供更高安全性,避免客户端密钥无法安全存储的问题。
适用场景: 无法安全存储密钥的移动应用、原生应用和公共客户端。
4. 客户端信任:防御凭据填充攻击(2025 年 11 月 14 日)
当用户从未识别的设备登录时,自动启用次要身份验证:
- 对密码有效但未启用 2FA 的用户生效
- 无需配置
- 所有 Clerk 套餐均包含此功能
工作原理: Clerk 检测到用户从新设备登录时,会自动提示进行额外验证(电子邮件验证码、备用码)。
5. 支持 Next.js 16(2025 年 11 月)
@clerk/nextjs v6.35.2+ 改进了 Next.js 16 中的缓存失效处理,适用于退出登录时。
关键模式与错误预防
Next.js v6:异步 auth() 助手函数
模式:
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { userId } = await auth() // ← Must await
if (!userId) {
return <div>Unauthorized</div>
}
return <div>User ID: {userId}</div>
}
Cloudflare Workers:authorizedParties(CSRF 防护)
重要: 始终设置 authorizedParties,以防止 CSRF 攻击
import { verifyToken } from '@clerk/backend'
const { data, error } = await verifyToken(token, {
secretKey: c.env.CLERK_SECRET_KEY,
// REQUIRED: Prevent CSRF attacks
authorizedParties: ['https://yourdomain.com'],
})
原因: 如果不设置 authorizedParties,攻击者就能使用来自其他域的有效令牌。
来源: https://clerk.com/docs/reference/backend/verify-token
JWT 模板 - 大小限制与短代码
JWT 大小限制:自定义声明为 1.2KB ⚠️
问题:浏览器 Cookie 的大小限制为 4KB。Clerk 的默认声明约占 2.8KB,因此自定义声明仅剩 1.2KB。
⚠️ 开发提示:在 Vite 开发模式下测试自定义 JWT 声明时,可能会遇到 “431 Request Header Fields Too Large” 错误。这是因为 Clerk 的 URL 握手令牌超过了 Vite 的 8KB 限制。解决方法请参见 Issue #11。
解决方案:
// ✅ GOOD: Minimal claims
{
"user_id": "{{user.id}}",
"email": "{{user.primary_email_address}}",
"role": "{{user.public_metadata.role}}"
}
// ❌ BAD: Exceeds limit
{
"bio": "{{user.public_metadata.bio}}", // 6KB field
"all_metadata": "{{user.public_metadata}}" // Entire object
}
最佳实践:将大型数据存储在数据库中,仅在 JWT 中包含标识符/角色。
可用简码参考
| 类别 | 简码 | 示例 |
|---|---|---|
| 用户 ID 和姓名 | {{user.id}}、{{user.first_name}}、{{user.last_name}}、{{user.full_name}} | "John Doe" |
| 联系方式 | {{user.primary_email_address}}、{{user.primary_phone_address}} | "[email protected]" |
| 个人资料 | {{user.image_url}}、{{user.username}}、{{user.created_at}} | "https://..." |
| 验证 | {{user.email_verified}}、{{user.phone_number_verified}} | true |
| 元数据 | {{user.public_metadata}}、{{user.public_metadata.FIELD}} | {"role": "admin"} |
| 组织 | org_id、org_slug、org_role(位于 sessionClaims 中) | "org:admin" |
高级功能:
- 字符串插值:
"{{user.last_name}} {{user.first_name}}" - 条件回退:
"{{user.public_metadata.role || 'user'}}" - 嵌套元数据:
"{{user.public_metadata.profile.interests}}"
官方文档:https://clerk.com/docs/guides/sessions/jwt-templates
使用 Clerk 进行测试
测试凭据(固定 OTP:424242)
测试邮箱(不发送邮件,使用固定 OTP):
[email protected]
[email protected]
测试电话号码(不发送短信,使用固定 OTP):
+12015550100
+19735550133
固定 OTP 代码:424242(适用于所有测试凭据)
生成会话令牌(有效期 60 秒)
脚本(scripts/generate-session-token.js):
# Generate token
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js
# Create new test user
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --create-user
# Auto-refresh token every 50 seconds
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --refresh
手动流程:
- 创建用户:
POST /v1/users - 创建会话:
POST /v1/sessions - 生成令牌:
POST /v1/sessions/{session_id}/tokens - 在请求头中使用:
Authorization: Bearer <token>
使用 Playwright 进行端到端测试
安装 @clerk/testing 以自动管理测试令牌:
npm install -D @clerk/testing
全局设置(global.setup.ts):
import { clerkSetup } from '@clerk/testing/playwright'
import { test as setup } from '@playwright/test'
setup('global setup', async ({}) => {
await clerkSetup()
})
测试文件(auth.spec.ts):
import { setupClerkTestingToken } from '@clerk/testing/playwright'
import { test } from '@playwright/test'
test('sign up', async ({ page }) => {
await setupClerkTestingToken({ page })
await page.goto('/sign-up')
await page.fill('input[name="emailAddress"]', '[email protected]')
await page.fill('input[name="password"]', 'TestPassword123!')
await page.click('button[type="submit"]')
// Verify with fixed OTP
await page.fill('input[name="code"]', '424242')
await page.click('button[type="submit"]')
await expect(page).toHaveURL('/dashboard')
})
官方文档:https://clerk.com/docs/guides/development/testing/overview
防止已知问题
此技能可防止 11 个已记录的问题:
问题 #1:缺少 Clerk 密钥
错误:"Missing Clerk Secret Key or API Key"
来源:https://stackoverflow.com/questions/77620604
预防措施:始终在 .env.local 中设置,或通过 wrangler secret put 设置
问题 #2:从 API Key 迁移到 Secret Key
错误:"apiKey is deprecated, use secretKey"
来源:https://clerk.com/docs/upgrade-guides/core-2/backend
预防措施:在所有调用中将 apiKey 替换为 secretKey
问题 #3:JWKS 缓存竞态条件
错误:"No JWK available" 来源:https://github.com/clerk/javascript/blob/main/packages/backend/CHANGELOG.md 预防措施:使用 @clerk/[email protected] 或更高版本(此问题已修复)
问题 #4:缺少 authorizedParties(CSRF)
错误:无错误,但存在 CSRF 漏洞
来源:https://clerk.com/docs/reference/backend/verify-token
预防措施:始终设置 authorizedParties: ['https://yourdomain.com']
问题 #5:导入路径变更(Core 2)
错误:"Cannot find module" 来源:https://clerk.com/docs/upgrade-guides/core-2/backend 预防措施:更新 Core 2 的导入路径
问题 #6:超出 JWT 大小限制
错误:令牌超出大小限制 来源:https://clerk.com/docs/backend-requests/making/custom-session-token 预防措施:将自定义声明控制在 1.2KB 以内
问题 #7:API 版本 v1 已弃用
错误:"API version v1 is deprecated" 来源:https://clerk.com/docs/upgrade-guides/core-2/backend 预防措施:使用最新的 SDK 版本(API v2025-11-10)
问题 #8:ClerkProvider JSX 组件错误
错误:"cannot be used as a JSX component" 来源:https://stackoverflow.com/questions/79265537 预防措施:确保 React 19 与 @clerk/[email protected]+ 兼容
问题 #9:对异步 auth() 辅助函数的困惑
错误:"auth() is not a function"
来源:https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6
预防措施:始终使用 await:const { userId } = await auth()
问题 #10:环境变量配置错误
错误:“缺少可发布密钥”或密钥泄露
预防措施:使用正确的前缀(NEXT_PUBLIC_、VITE_),切勿提交密钥
问题 #11:431 请求标头字段过大(Vite 开发模式)
错误:登录时出现“431 请求标头字段过大”
来源:在 Vite 开发模式下测试自定义 JWT 声明时很常见
原因:URL 中的 Clerk __clerk_handshake 令牌超出 Vite 的 8KB 标头限制
预防措施:
添加到 package.json:
{
"scripts": {
"dev": "NODE_OPTIONS='--max-http-header-size=32768' vite"
}
}
临时解决方法:清除浏览器缓存,退出登录,然后重新登录
原因:Clerk 开发令牌比生产令牌更大;自定义 JWT 声明会增加握手令牌的大小
注意:这与问题 #6(会话令牌大小)不同。问题 #6 涉及 Cookie(1.2KB),而这里涉及开发模式下的 URL 参数(8KB → 32KB)。
官方文档
- Clerk 文档:https://clerk.com/docs
- Next.js 指南:https://clerk.com/docs/references/nextjs/overview
- React 指南:https://clerk.com/docs/references/react/overview
- 后端 SDK:https://clerk.com/docs/reference/backend/overview
- JWT 模板:https://clerk.com/docs/guides/sessions/jwt-templates
- API 版本 2025-11-10 升级指南:https://clerk.com/docs/guides/development/upgrading/upgrade-guides/2025-11-10
- 测试指南:https://clerk.com/docs/guides/development/testing/overview
- Context7 库 ID:
/clerk/clerk-docs
软件包版本
最新版本(2025 年 11 月 22 日):
{
"dependencies": {
"@clerk/nextjs": "^6.35.4",
"@clerk/clerk-react": "^5.56.2",
"@clerk/backend": "^2.23.2",
"@clerk/testing": "^1.13.18"
}
}
令牌效率:
- 不使用 skill:约 5,200 个令牌(设置教程、JWT 模板、测试设置)
- 使用 skill:约 2,500 个令牌(破坏性变更 + 关键模式 + 错误预防)
- 节省:约 52%(约 2,700 个令牌)
预防的错误:11 个有详细解决方案的已记录问题 核心价值:API 2025-11-10 破坏性变更、Next.js v6 异步 auth()、自定义 OAuth 的 PKCE、防止凭据填充攻击、JWT 大小限制、431 标头错误解决方法
上次验证时间:2025-11-22 | Skill 版本:2.0.0 | 变更:新增 API 版本 2025-11-10 破坏性变更(计费端点)、PKCE 支持、Client Trust 防御、Next.js 16 支持。移除教程(约 480 行)。更新 SDK 版本。聚焦于破坏性变更 + 错误预防 + 关键模式。