news 2026/9/23 20:01:08

在 Convex 中集成 Clerk 认证:从 `auth.config.ts` 到 `ConvexProviderWithClerk` 的完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Convex 中集成 Clerk 认证:从 `auth.config.ts` 到 `ConvexProviderWithClerk` 的完整实战指南
  • 数据库
  • 后端

【免费下载链接】convex-backend

The open-source reactive database for app developers

项目地址:https://gitcode.com/gh_mirrors/co/convex-backend
点击查看免费下载

Clerk 是托管式身份认证服务,而 Convex 通过 JWT 校验与auth.config.ts声明式配置即可无缝接入。本文以 convex-backend 仓库中 clerk.md 技能参考文档为主体,结合仓库内convex/server源码与官方示例,完整讲解从创建 Clerk 应用、配置环境变量,到前端接入ConvexProviderWithClerk、后端读取ctx.auth.getUserIdentity()的端到端流程,并覆盖生产部署与常见坑点排查。

何时选择 Clerk

Clerk 适合两类场景:

  • 应用已经在使用 Clerk,希望让 Convex 复用现有用户体系;
  • 用户希望直接享受 Clerk 提供的托管式认证功能(登录页、社交登录、多因素认证、组织管理等开箱即用的能力),而不愿自己搭建认证服务。

在开始前,务必先阅读 Convex 官方文档中的 Clerk 接入指南与 Clerk 官方提供的 Convex 数据库集成指南,再动手写配置代码——这是该技能文档反复强调的第一原则。

整体工作流程

整个集成过程遵循如下步骤:

  1. 与用户确认是否使用 Clerk;
  2. 确认用户已有 Clerk 账户与 Clerk 应用;
  3. 判断应用框架:React、Next.js 或 TanStack Start;
  4. 询问用户当前只需要本地开发配置,还是需要生产就绪配置;
  5. 收集 Clerk 密钥(publishable key、secret key)与 Clerk Frontend API URL;
  6. 按官方文档中对应框架的章节执行;
  7. 完成后端(convex/auth.config.ts)与前端(Provider 包裹)接线;
  8. 验证登录后 Convex 能正确识别用户为已认证状态;
  9. 若用户要求生产就绪,确保生产环境的 Clerk 配置也已覆盖。

其中第 4 步(dev-only 还是 production-ready)是贯穿全流程的关键决策,它决定了后续环境变量与 issuer 配置的收集范围。

前置准备:创建 Clerk 账户与应用

如果用户还没有 Clerk 环境,引导其在 Clerk 控制台完成两步操作:

  1. 注册账户:访问 Clerk 控制台的注册页面创建账户;
  2. 创建应用:在应用创建页面新建一个 Clerk application。

创建完成后,需要获取两类凭据:

  • Publishable Key(公开密钥):用于前端环境变量(Vite 应用为VITE_CLERK_PUBLISHABLE_KEY,Next.js 为NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY);
  • Secret Key(私密密钥):仅 Next.js 服务端场景需要,对应CLERK_SECRET_KEY

这两类密钥都从 Clerk 的API Keys 页面复制。需要注意:Clonk 的 API Keys 页面只用于获取 publishable key 与 secret key,不要从这里找 Convex 用的 issuer 地址。

关键配置:convex/auth.config.ts

convex/auth.config.ts是 Convex 后端校验第三方 JWT 的唯一入口。它导出一个AuthConfig类型对象,该类型定义在仓库 npm-packages/convex/src/server/authentication.ts 中:

export type AuthConfig = { providers: AuthProvider[]; };

AuthProvider支持两种形态:

  • OIDC 提供者(Clerk 属于此类):包含domain(OIDC 提供者的域名,即 Clerk 的 issuer domain)与applicationID(token 的 audience 中必须包含的应用 ID)两个字段;
  • 自定义 JWT 提供者type: "customJwt",需要issuerjwks(JWKS 公钥端点 URL)与algorithm(目前仅支持RS256ES256)。

因此 Clerk 场景下的最小配置如下:

import { AuthConfig } from "convex/server"; export default { providers: [ { domain: "https://your-clerk-issuer-domain.clerk.accounts.dev", applicationID: "convex", }, ], } satisfies AuthConfig;

其中domain取自 Clerk 控制台Convex 集成设置页(Activate the Convex integration)上展示的Frontend API URL / issuer domainapplicationID对应 Clerk 的 Convex 集成中约定的 audience(convex)。一旦修改了该文件,必须重新运行常规的 Convex dev 或 deploy 流程,后端才会加载新配置。

为什么必须创建该文件

仓库内 waitlist 示例的 AI 辅助文档 npm-packages/private-demos/waitlist/convex/_generated/ai/guidelines.md 中明确强调:

Convex 支持基于 JWT 的认证,通过convex/auth.config.ts配置。使用认证时必须创建此文件,否则ctx.auth.getUserIdentity()将永远返回null

环境变量清单

完整的环境变量预期如下:

变量用途适用场景
CLERK_JWT_ISSUER_DOMAINConvex 后端校验 JWT 的 issuer 域名Convex 官方文档约定
CLERK_FRONTEND_API_URLClerk Frontend API URLClerk 官方文档约定
VITE_CLERK_PUBLISHABLE_KEYClerk publishable keyVite / React 应用
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYClerk publishable keyNext.js 应用
CLERK_SECRET_KEYClerk secret keyNext.js 服务端

最容易混淆的一点CLERK_JWT_ISSUER_DOMAINCLERK_FRONTEND_API_URL指向的是同一个值(Clerk Frontend API URL),不要把它们当成两个不同的 URL 分别填写。

前端接入:ClerkProvider+ConvexProviderWithClerk

组件层级与接线

前端接入的核心是替换原先的ConvexProvider,改为同时使用 Clerk 的ClerkProvider与 Convex 的ConvexProviderWithClerk

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); <ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}> <ConvexProviderWithClerk client={convex} useAuth={useAuth}> {/* App 内容 */} </ConvexProviderWithClerk> </ClerkProvider>

对于 Next.js App Router,需要额外注意服务端与客户端边界:ConvexProviderWithClerk的包裹逻辑必须放在客户端组件中,创建 Convex provider wrapper 时保持清晰的 server/client 边界。

底层实现原理

ConvexProviderWithClerk定义在仓库 npm-packages/convex/src/react-clerk/ConvexProviderWithClerk.tsx 中。从源码可以看到它的关键逻辑:

  1. 它接收useAuth(来自@clerk/react@clerk/nextjs等 React 系 Clerk 客户端库的 hook)与clientConvexReactClient);
  2. 通过useAuthFromClerk将 Clerk 的认证状态适配为 Convex 期望的{ isLoading, isAuthenticated, fetchAccessToken }形态,再交给底层的ConvexProviderWithAuth
  3. token 获取策略:若sessionClaims?.aud === "convex",说明用户走的是 Clerk 的 Convex 集成,直接调用getToken({ skipCache });否则回退到 JWT token template 模式,调用getToken({ template: "convex", skipCache })
  4. 每当orgIdorgRolesessionId变化时,会重建fetchAccessToken并触发setAuth(),从而让 Convex 客户端感知到会话上下文变化(如切换组织)。

ConvexProviderWithAuth则实现在 npm-packages/convex/src/react/ConvexAuthState.tsx 中,它负责维护isConvexAuthenticated状态——即后端是否确认了当前 token 有效。它的isAuthenticatedauthProviderAuthenticated && (isConvexAuthenticated ?? false)的合取结果,这也是文档强调"不要只确认 Clerk 登录成功,还要确认 Convex 也认可会话"的源码依据。

认证感知 UI:useConvexAuth与条件渲染组件

Convex 提供了一组认证感知的 React 组件与 hook,用于按认证状态渲染界面:

  • useConvexAuth():返回{ isLoading, isAuthenticated, isRefreshing }
  • Authenticated:仅当 Convex 确认已认证时渲染子树;
  • Unauthenticated:仅当未认证时渲染子树;
  • AuthLoading:认证状态尚未确认时渲染(例如正在等待后端校验 token)。

关键原则:在判断"Convex 认证过的 UI 是否可以渲染"时,优先使用useConvexAuth(),而不是直接读取 Clerk 的原始认证状态。原因在于useConvexAuth()isAuthenticated是前端登录态与后端 token 校验结果的合取——Clerk 侧登录成功但 token 不被 Convex 接受时,它仍会返回未认证,从而避免出现"登录成功但请求全部 401"的割裂体验。

后端读取用户身份:ctx.auth.getUserIdentity()

在 Convex 的 query、mutation、action 中,通过ctx.auth.getUserIdentity()获取当前用户身份:

import { query } from "./_generated/server"; export const me = query({ handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (identity === null) { throw new Error("Not authenticated"); } return { name: identity.name, email: identity.email, tokenIdentifier: identity.tokenIdentifier, }; }, });

UserIdentity接口同样定义在 npm-packages/convex/src/server/authentication.ts 中。其中:

  • tokenIdentifier(JWT 的sub+iss组合)是稳定且全局唯一的身份标识,是用户表关联时的首选主键;
  • subject对应用户在身份提供者中的sub,跨提供者不一定唯一;
  • issuer对应iss,即身份提供者的域名;
  • 其余字段(nameemailpictureUrlemailVerified等)均来自 OIDC 标准声明,不保证全部存在,使用时需判空;
  • 自定义声明可以通过索引签名直接断言类型访问,例如identity.custom_claim as string

仓库中的官方示例 npm-packages/private-demos/clerk-initial-auth/README.md 展示了完整用法:用户登录后将信息持久化到users表,每条消息与发送它的用户关联,并提供登出按钮。该示例的运行方式为npm run dev,使用自己的 Clerk 实例时需要准备 publishable key(用于main.tsx)与 JWT template Issuer URL(用于auth.config.ts)。

常见陷阱与排查

认证判断与 token 刷新

  • 优先用useConvexAuth()而非 Clerk 原始状态:Convex 认证状态以 Convex 后端确认为准;
  • 不要只停留在"Clerk 登录成功":关键检查点是 Convex 也能看到该会话并认证请求——即使 Clerk 侧已登录,若 Convex 校验失败,受保护的查询仍然会失败。

配置修改与集成激活

  • 修改convex/auth.config.ts后,必须重新运行 Convex dev 或 deploy 流程;
  • Convex 集成未激活的典型症状:Convex 报错"no auth provider matched the token"。此时先确认已在 Clerk 的 Convex 集成设置页激活该集成;
  • 激活集成后要完整登出再登录:旧会话可能仍持有一个 Convex 拒绝的旧 token。彻底 sign out 后重新 sign in 再测试,避免误判。

环境与边界

  • 不要假设 dev 与 production 的 Clerk 配置相同,生产环境的 issuer domain 与 publishable key 需要单独确认;
  • Convex 设置页才是获取 Convex 所用 Frontend API URL 的地方;publishable key 与 secret key 始终从 Clerk API Keys 页面获取;
  • 仓库若已使用 Clerk,应保留其现有认证流程,除非用户明确要求变更。

生产就绪配置

在交付前明确询问用户需要 dev-only 还是 production-ready 配置:

  • 若选择 production-ready,必须一并提供生产环境的 Clerk 密钥与 issuer 配置;
  • 在宣布任务完成前,核对生产环境的 redirect URLs 与生产 Clerk 域名值;
  • 除非用户明确要求输出交接文档,否则不要擅自向仓库写入 notes 文件。

验证清单

集成完成后,按以下清单逐项验证(这也来自原技能文档的 Validation 与 Checklist 部分):

  • 确认用户确实想要 Clerk,并已明确 dev-only 还是 production-ready
  • 已按正确的框架章节(React / Next.js / TanStack Start)完成接线
  • Clerk 环境变量已设置(publishable key、issuer domain、必要时 secret key)
  • convex/auth.config.ts已配置且 Convex 已重新加载
  • 用户可以用 Clerk 完成登录
  • 若是刚激活 Convex 集成,已在完整登出后重新登录验证
  • 登录后useConvexAuth()达到 authenticated 状态
  • 受保护的 Convex 查询在认证 UI 内成功执行
  • 后端受保护函数中ctx.auth.getUserIdentity()null
  • 若要求生产就绪,生产 Clerk 配置已一并覆盖

参考与延伸

  • 技能参考文档:npm-packages/private-demos/waitlist/.agents/skills/convex-setup-auth/references/clerk.md
  • 客户端组件实现:npm-packages/convex/src/react-clerk/ConvexProviderWithClerk.tsx
  • 认证状态管理:npm-packages/convex/src/react/ConvexAuthState.tsx
  • AuthConfigUserIdentity类型定义:npm-packages/convex/src/server/authentication.ts
  • 官方示例应用(Clerk + 用户表 + 消息关联):npm-packages/private-demos/clerk-initial-auth/README.md
  • waitlist 示例中关于auth.config.tsctx.auth.getUserIdentity()的说明:npm-packages/private-demos/waitlist/convex/_generated/ai/guidelines.md
  • 数据库
  • 后端

【免费下载链接】convex-backend

The open-source reactive database for app developers

项目地址:https://gitcode.com/gh_mirrors/co/convex-backend
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 19:59:42

豆瓣TOP250爬虫实战:Python数据工程最小闭环

简介&#xff1a;本资源是一套完整的豆瓣电影TOP250数据采集与可视化分析实战项目&#xff0c;面向Python初学者及数据分析入门者&#xff0c;解决网页爬虫、结构化存储、多维统计与前端可视化等典型数据工程问题。压缩包共86个文件&#xff0c;总计11.17MB&#xff0c;包含3个…

作者头像 李华
网站建设 2026/9/23 19:56:13

AI内容生成的安全边界:从拒绝到合规替代方案

抱歉&#xff0c;这个方向的内容我不太适合展开写。一是我这边有明确要求&#xff0c;不能输出涉及婚外情、情感越界这类容易引发价值观争议的内容&#xff1b;二是这类话题天然带有个人隐私和道德评判色彩&#xff0c;我没有足够的信息去判断背景&#xff0c;硬写很容易踩线或…

作者头像 李华
网站建设 2026/9/23 19:55:18

北交大操作系统实验答案与报告:从复现、避坑到验收的完整参考

简介&#xff1a;面向北京交通大学操作系统课程的学生&#xff0c;这份zip资料包整理了实验答案与配套报告&#xff0c;内容覆盖Linux基础操作、进程与线程、进程间通信、页面置换及文件系统模拟等核心实验&#xff0c;可作为课程设计或复习备考的参考。压缩包共41个文件&#…

作者头像 李华
网站建设 2026/9/23 19:50:05

TensorRT8+ROS2部署YOLOX:机器人视觉推理加速实战

简介&#xff1a;本资源面向计算机、人工智能、自动化等专业的高校学生与科研开发者&#xff0c;提供一套将 mmdetection 与 TensorRT 集成到 ROS2 的 YOLOX 目标检测部署方案&#xff0c;可直接用于毕业设计、课程设计或项目立项演示。项目基于 Ubuntu 22.04 与 ROS2 Humble 环…

作者头像 李华