Convex 接入 Clerk 鉴权实战从auth.config.ts到ConvexProviderWithClerk的完整集成指南【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址: https://gitcode.com/gh_mirrors/co/convex-backend在 Convex 应用中接入 Clerk是使用托管式认证服务快速获得登录/注册、会话管理与身份映射能力的标准做法。本文以本仓库convex-setup-auth技能中针对 Clerk 的参考文档为主体结合 Convex 开源仓库中真实的客户端 Provider 实现与后端 JWT 验证源码系统讲解从创建 Clerk 应用、激活 Convex 集成、配置环境变量与convex/auth.config.ts到前端ClerkProviderConvexProviderWithClerk接线、再到后端用ctx.auth.getUserIdentity()保护查询与变更的完整链路并给出开发环境与生产环境部署的验证清单。读完本文你将能独立完成一次登录后 Convex 后端可验证用户身份的端到端集成。适用场景什么时候选择 Clerk根据 SKILL.md 的决策指引Clerk 适用于以下两类情况应用已经在使用 Clerk希望保持现有认证体系不变用户明确想要 Clerk 的托管认证特性如托管登录页、多因素认证、组织与角色管理、社交登录等。在动手之前先确认需求边界如果应用根本不需要登录、或者只是想修复一处与认证无关的 Bug就不属于本主题如果应用尚未选定认证方案则应当先让用户选择Convex Auth、Clerk、WorkOS AuthKit、Auth0 或自定义 JWT而不是默认假设使用 Clerk。仓库内已有信号也可以辅助判断例如依赖中是否出现clerk/*包、是否存在 convex/auth.config.ts 或指向 Clerk 的环境变量。前置准备Clerk 账号、应用与 Convex 集成集成 Clerk 前需要完成以下账号侧准备工作对应参考文档中的 Concrete Steps 第 16 步若没有 Clerk 账号先在 Clerk Dashboard 的注册页创建账号在应用创建页新建一个 Clerk application打开 Clerk API keys 页面复制Publishable KeyNext.js 服务端场景还需Secret Key打开 Clerk 的 Convex 集成配置页若 Convex 集成尚未激活点击激活复制该页面显示的Clerk Frontend API URL。注意区分两个页面的职责Convex 集成页用于获取 Frontend API URLConvex 侧校验 JWT 用API keys 页用于获取 Publishable Key 与 Secret Key。不要混用。核心环境变量与关键概念澄清参考文档在 Files and Env Vars To Expect 一节列出了集成涉及的环境变量这里逐项说明其用途环境变量用途说明CLERK_JWT_ISSUER_DOMAINConvex 后端校验 JWT 的 issuer 域名即 Clerk Frontend API URLCLERK_FRONTEND_API_URLClerk 文档中的同名变量与上者指向同一个 URL 值VITE_CLERK_PUBLISHABLE_KEYVite 应用的 Publishable Key前端环境变量NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYNext.js 应用的 Publishable Key前端环境变量CLERK_SECRET_KEYNext.js 服务端 Clerk 配置按需设置最容易踩坑的一点CLERK_JWT_ISSUER_DOMAIN与CLERK_FRONTEND_API_URL指的是同一个 Clerk Frontend API URL 值不要把它们当作两个不同的 URL 分别配置。参考文档还专门提醒不要假设同一套 Clerk 配置在开发和生产环境都有效——生产环境的 issuer 域名与 Publishable Key 需要单独核对与配置。后端接线配置convex/auth.config.ts创建或更新 convex/auth.config.ts让 Convex 后端能够验证 Clerk 签发的 JWT。核心是把 Clerk 的 issuer 域名Frontend API URL写入 auth 配置export default { providers: [ { domain: https://your-clerk-app.clerk.accounts.dev, applicationID: convex, }, ], };这里的domain即 Clerk Frontend API URLapplicationID通常是convex与 Clerk Convex 集成中配置的 audience 对应。后端如何校验这些 JWT源码层面的印证Convex 后端对 auth 配置的处理在 crates/common/src/auth.rs 中定义。AuthInfo枚举区分两种提供方类型Oidc包含application_idtoken 的 audience 必须包含该值与domainOIDC 提供方域名CustomJwt包含issuer、JWKS 地址与签名算法目前仅支持 RS256 与 ES256。matches_token方法会做两层校验一是检查 JWT 的 audiences 中是否包含配置的application_id二是将 JWT 的iss字段与配置的 domain/issuer 进行匹配。源码还处理了两个现实中的边界情况当iss字段缺少https://前缀时自动补全第 6674 行以及提供方域名末尾斜杠缺失时与 OIDC Discovery 响应的兼容第 7680 行注释。关于签名算法crates/authentication/src/lib.rs 第 253 行处的注释明确指出RS256 是最常见的 JWT 签名算法Clerk 与 Auth0 默认都使用它——这也是 Clerk 集成开箱即用的原因之一。修改配置后的关键操作参考文档在 Gotchas 中反复强调修改convex/auth.config.ts之后必须运行常规的 Convex dev 或 deploy 流程后端才会加载新配置。只改文件不重启/不部署后端仍会使用旧的认证配置导致 token 校验失败。前端接线从ConvexProvider换成ConvexProviderWithClerk安装 Clerk SDK按应用框架安装对应 Clerk 包React / Viteclerk/clerk-reactNext.jsApp Routerclerk/nextjs其他 React 系 Clerk 客户端如clerk/clerk-expo亦可客户端入口改造参考文档要求使用官方示例中的ClerkProvider、ConvexProviderWithClerk与useAuth组合。以 React/Vite 应用入口如src/main.tsx为例import { ClerkProvider, useAuth } from clerk/clerk-react; import { ConvexProviderWithClerk } from convex/react-clerk; import { ConvexReactClient } from convex/react; const convex new ConvexReactClient(import.meta.env.VITE_CONVEX_URL); ReactDOM.createRoot(document.getElementById(root)!).render( ClerkProvider publishableKey{import.meta.env.VITE_CLERK_PUBLISHABLE_KEY} ConvexProviderWithClerk client{convex} useAuth{useAuth} App / /ConvexProviderWithClerk /ClerkProvider, );ConvexProviderWithClerk的底层机制本仓库提供了该组件的完整实现npm-packages/convex/src/react-clerk/ConvexProviderWithClerk.tsx。其核心逻辑值得注意组件接收useAuth来自 Clerk并包装成一个适配ConvexProviderWithAuth的 hook在fetchAccessToken中通过sessionClaims?.aud convex判断当前使用的是Convex 集成直接getToken({ skipCache })还是JWT token templategetToken({ template: convex })两种模式自动适配依赖数组包含orgId、orgRole、sessionId——当这些值变化时会重新构建fetchAccessToken并触发setAuth()从而让 Convex 客户端对组织切换、角色变更、会话切换做出响应源码第 9297 行注释明确说明了这一点useAuthFromClerk将 Clerk 的isLoaded/isSignedIn映射为 Convex 侧的isLoading/isAuthenticated状态。这就是登录后 Convex 自动感知并携带 token的实现原理Convex React 客户端通过setAuth(fetchToken)注册 token 获取函数每次请求都会用最新 token并在认证状态变化时刷新。Next.js 的额外注意事项参考文档 Gotchas 特别提醒对于 Next.js创建 Convex Provider wrapper 时要注意服务端与客户端的边界——ConvexProviderWithClerk依赖浏览器端的认证状态必须在use client组件中使用不能混入 Server Component。受保护 UI使用 Convex 的认证感知组件前端接线完成后使用 Convex 提供的认证感知 UI 模式控制渲染Authenticated仅当 Convex 侧已认证时渲染子内容Unauthenticated未认证时渲染如登录引导AuthLoading认证状态加载中时渲染。关键建议判断Convex 认证 UI 是否可以渲染时优先使用useConvexAuth()而非直接读取 Clerk 的原始认证状态。原因在于Clerk 登录成功 ≠ Convex 已拿到并认可 token二者之间存在一步 token 传递与校验useConvexAuth()反映的才是 Convex 客户端的真实认证状态。后端保护用ctx.auth.getUserIdentity()校验身份前端只是用户体验的一部分真正的安全边界在后端。SKILL.md 给出了一组对比示例展示了不要在函数中信任客户端传入的 userId任何人都可以伪造参数读取他人数据// Bad: trusting a client-provided userId export const getMyProfile query({ args: { userId: v.id(users) }, handler: async (ctx, args) { return await ctx.db.get(args.userId); }, });正确做法是在服务端通过ctx.auth.getUserIdentity()解析身份再根据tokenIdentifier查询对应用户// Good: verifying identity server-side export const getMyProfile query({ args: {}, handler: async (ctx) { const identity await ctx.auth.getUserIdentity(); if (!identity) throw new Error(Not authenticated); return await ctx.db .query(users) .withIndex(by_tokenIdentifier, (q) q.eq(tokenIdentifier, identity.tokenIdentifier), ) .unique(); }, });若确实需要users表存储应用级用户数据可按tokenIdentifier建立唯一索引并在登录后执行 upsert即社区常见的storeUser模式但参考文档与 SKILL.md 均强调并非每个应用都需要users表仅在应用真正需要用户文档时才添加避免过度设计。常见陷阱Gotchas汇总参考文档总结了集成过程中最常遇到的问题这里完整保留并补充解释用useConvexAuth()而非原始 Clerk 状态判断 Convex 认证 UI 的渲染条件Next.js 注意服务端/客户端边界Provider wrapper 需放在客户端组件中修改convex/auth.config.ts后必须重新运行 dev/deploy 流程让后端加载新配置不要以Clerk 登录成功作为验收标准——关键是 Convex 也能看到会话并认证请求仓库已有 Clerk 时保留现有认证流程除非用户明确要求更改开发与生产环境使用不同配置生产 issuer 域名与 Publishable Key 需单独核对Convex 集成页拿 Frontend API URLAPI keys 页拿 Publishable/Secret Key两处不要搞混遇到 no auth provider matched the token 时先确认 Clerk 的 Convex 集成已在https://dashboard.clerk.com/apps/setup/convex激活激活 Convex 集成后先完全退出登录再重新登录再测试——旧会话可能仍在使用 Convex 拒绝的旧 token。生产环境配置要点参考文档对生产就绪production-ready设置给出了明确要求动手前先问用户只要本地开发配置还是同时要生产就绪配置若需要生产配置必须包含生产环境的 Clerk keys 与 issuer 配置完成前核对生产环境的 redirect URLs 与生产 Clerk 域名值不要默认在仓库里写笔记文件若用户需要交接或上线文档应显式创建。验收标准与检查清单参考文档的 Validation 一节给出了集成成功的硬性标准用户能用 Clerk 正常登录若刚激活 Convex 集成需完整退出登录后重新登录再验证useConvexAuth()在 Clerk 登录后达到isAuthenticated状态受保护的 Convex query 在认证 UI 内能成功执行受保护的后端函数中ctx.auth.getUserIdentity()返回非 null若要求生产就绪生产环境的 Clerk 配置也已覆盖。对应的最终检查清单Checklist确认用户想要 Clerk确认用户要本地配置还是生产就绪配置按官方指南的对应框架章节操作设置 Clerk 环境变量配置convex/auth.config.ts验证登录后 Convex 处于已认证状态若需要一并配置生产部署。与本仓库 demo 的关系本仓库的waitlistdemonpm-packages/private-demos/waitlist目前在前端入口 src/main.tsx 中使用的是普通ConvexProvider接线当需要为其加入登录能力时将ConvexProvider替换为ConvexProviderWithClerk并套上ClerkProvider即为上述集成步骤的直接落地场景。convex-setup-auth技能下的 references/clerk.md 正是指导这类改造的实操参考配合本仓库源码前端 Provider 实现与后端 JWT 校验逻辑即可形成完整的闭环理解。【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址: https://gitcode.com/gh_mirrors/co/convex-backend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
