- 数据库
- 后端
【免费下载链接】convex-backend
The open-source reactive database for app developers
本文基于 convex-backend 仓库中 SvelteKit 快速开始项目的 convex-setup-auth 技能参考文档 编写,系统讲解在 Convex 应用中接入 Auth0 认证的完整流程。读完本文,你将掌握:如何在已有或全新 Auth0 租户上创建 SPA 应用、如何配置convex/auth.config.ts让 Convex 校验 Auth0 签发的 JWT、如何用Auth0Provider与ConvexProviderWithAuth0完成前后端接线、如何用ctx.auth.getUserIdentity()保护后端函数,以及如何区分"Auth0 登录成功"与"Convex 识别会话成功"这两个关键验证点。
适用场景与前置判断
Auth0 集成并非 Convex 认证的唯一选项,动手前必须先确认选型。根据技能文档的指引,Convex 支持多种认证方案:
- Convex Auth:希望认证逻辑完全由 Convex 托管时的默认选择;
- Clerk:应用已使用 Clerk 或需要 Clerk 托管认证能力;
- WorkOS AuthKit:应用已使用 WorkOS 或指定 AuthKit;
- Auth0:应用已经使用 Auth0,或用户明确指定 Auth0(本文主题);
- 自定义 JWT 提供方:集成上述之外已有的认证系统。
判断依据可以从仓库中已有的痕迹获得:依赖包(如@auth0/*、@clerk/*)、已有文件(如convex/auth.config.ts、auth 中间件、provider 包装组件或登录组件)、指向特定提供方的环境变量。只有当仓库已使用 Auth0 或用户明确选择 Auth0 时,才走本文的 Auth0 路径。
此外,在动手前必须确认两个关键问题:
- 应用框架与 Auth0 现状:应用是 React、Next.js 还是 SvelteKit?Auth0 是否已部分接入?
- 目标范围:用户需要 local-only 开发环境配置,还是 production-ready 生产配置?这决定了后续租户、回调地址与环境变量的覆盖范围。
两条设置路径:Auth0 CLI 与 Dashboard
原文档给出了两条并行的 Auth0 应用创建路径,核心取舍是"速度"与"可控性"。
路径一:Auth0 CLI(最快路径)
如果用户愿意安装 Auth0 CLI,可以用它完成绝大多数机械性设置:
- 安装 Auth0 CLI;
- 用户执行
auth0 login完成 CLI 与 Auth0 租户的认证(这是唯一必须由用户完成的人工步骤); - 若创建新应用,使用
auth0 apps create并指定 SPA 类型,同时配置 callback URL(回调地址)、logout URL(登出地址)与 web origins(允许的 Web 来源); - 从 CLI 输出中获取 Auth0 domain 与 client ID。
文档明确提醒:CLI 路径虽快,但"尚未被验证为完全端到端可用的路径"(not a fully validated end-to-end path yet),尤其 refresh-token(刷新令牌)链路在验证中曾出现失败,因此不应把这条路径描述为已经彻底跑通。
路径二:Auth0 Dashboard(手动路径)
若用户不愿安装 CLI,则按框架完成 Auth0 前端 quickstart,并在 Dashboard 中手动创建 Auth0 应用,随后从 Dashboard 获取 domain 与 client ID。
无论走哪条路径,拿到Auth0 domain(形如your-tenant.auth0.com)与client ID都是后续所有配置的前提。
安装框架对应的 Auth0 SDK
前端接线的前提是为应用框架安装 Auth0 SDK。对于 React 生态是@auth0/auth0-react,其他框架(如 SvelteKit、Next.js、Vue)应遵循各自框架的 Auth0 quickstart 选择对应 SDK。仓库中可找到 React 生态的接入示例,例如 react-vite-ts 快速开始的 Auth0 接线文件 与 ConvexProviderWithAuth0 官方实现。
文档特别强调:Convex 官方 Auth0 文档假设 Auth0 侧已经设置完成,因此如果应用是从零开始,不要跳过 Auth0 前端 quickstart,否则后续登录流程必然失败。
后端配置:convex/auth.config.ts
convex/auth.config.ts是 Convex 校验第三方 JWT 的入口文件,位于项目根目录的convex/目录下。它导出一个满足AuthConfig类型的默认对象。从仓库源码 server/authentication.ts 可以看到该类型的真实定义:
export type AuthConfig = { providers: AuthProvider[]; };其中AuthProvider是联合类型,Auth0 属于OIDC provider分支,只需要两个字段:
domain:OIDC 提供方(Auth0 租户)的域名,对应 Auth0 的AUTH0_DOMAIN;applicationID:令牌(token)中audience(受众)必须包含的应用 ID,对应 Auth0 的 client ID。
因此,典型的 Auth0 配置形如:
import { AuthConfig } from "convex/server"; export default { providers: [ { domain: "https://your-tenant.auth0.com", applicationID: "your-auth0-client-id", }, ], } satisfies AuthConfig;关键点是domain 与 applicationID 必须与 Auth0 应用完全一致。文档的 Gotchas 中特别指出:"如果登录成功但 Convex 仍报告未认证,请双重检查convex/auth.config.ts以及后端配置是否已同步"——即修改该文件后,必须运行正常的 Convex dev 或 deploy 流程,让后端加载新配置(例如npx convex dev或npx convex deploy),否则 Convex 后端仍在使用旧配置校验令牌。
环境变量:本地与生产
Auth0 集成涉及前端与后端两组环境变量,文档列出的常见变量包括:
| 变量 | 用途 | 典型场景 |
|---|---|---|
AUTH0_DOMAIN | Auth0 租户域名 | 后端 / 服务端配置 |
AUTH0_CLIENT_ID | Auth0 应用客户端 ID | 后端 / 服务端配置 |
VITE_AUTH0_DOMAIN | 暴露给前端构建的域名 | Vite 系前端(VITE_前缀变量会打入前端包) |
VITE_AUTH0_CLIENT_ID | 暴露给前端构建的客户端 ID | Vite 系前端 |
对于 SvelteKit 应用,前端环境变量通常以PUBLIC_前缀暴露,例如在 SvelteKit 快速开始的 +layout.svelte 中可以看到PUBLIC_CONVEX_URL通过$env/static/public导入的用法,Auth0 的前端变量应遵循同样的公共变量暴露方式。
文档强调三点:
- dev 与 prod 环境分离:如果项目使用不同的 Auth0 环境,请保持开发租户与生产租户分开,不要假设本地租户配置与生产一致,生产环境的 domain、client ID 和回调地址必须单独核验;
- 本地回调地址必须匹配真实端口:开发时 Auth0 应用设置中的 callback URL、logout URL 与 web origins 必须与应用实际监听的本地端口一致,否则回调会被 Auth0 拒绝;
- 存量应用保持现状:如果仓库已经使用 Auth0,保留既有 redirect 与租户配置,除非用户明确要求更改。
前端接线:Auth0Provider + ConvexProviderWithAuth0
完成 SDK 安装与 Auth0 应用创建后,需要在应用入口处完成两层 Provider 嵌套。
第一层:Auth0Provider(来自 Auth0 SDK),负责 Auth0 登录态管理,传入 Auth0 域名与客户端 ID:
import { Auth0Provider } from "@auth0/auth0-react"; <Auth0Provider domain={AUTH0_DOMAIN} clientId={AUTH0_CLIENT_ID} authorizationParams={{ redirect_uri: window.location.origin, }} > {/* 应用内容 */} </Auth0Provider>第二层:ConvexProviderWithAuth0(来自convex/react),负责把 Auth0 的登录态桥接到 Convex 客户端。查看仓库中的 ConvexProviderWithAuth0.tsx 实现,可以看到它的核心机制:
- 它内部调用
useAuth0()获取isLoading、isAuthenticated与getAccessTokenSilently; - 通过
fetchAccessToken回调,在 Convex 每次需要令牌时调用getAccessTokenSilently({ detailedResponse: true, cacheMode: ... }),并把返回的id_token(而非 access token)交给 Convex; forceRefreshToken为 true 时以cacheMode: "off"强制刷新令牌,否则使用缓存;- 令牌获取失败时返回
null,从而让 Convex 判定为未认证。
典型接线方式是把原先的纯ConvexProvider替换为ConvexProviderWithAuth0,并让ConvexProviderWithAuth0嵌套在Auth0Provider内部:
import { ConvexProviderWithAuth0 } from "convex/react"; <Auth0Provider domain={AUTH0_DOMAIN} clientId={AUTH0_CLIENT_ID}> <ConvexProviderWithAuth0 client={convex}> <App /> </ConvexProviderWithAuth0> </Auth0Provider>文档明确要求使用官方示例中的 Provider 配置,不要自行改写,因为id_token的传递方式与刷新策略直接决定了 Convex 能否完成令牌校验。
用 Convex auth state 控制 UI
接入完成后,是否渲染依赖 Convex 数据的 UI,必须以 Convex 的认证状态为准,而不是以 Auth0 自身的状态为准。这是因为 Auth0 登录成功只代表"用户已在 Auth0 会话中",而 Convex 还需要拿到有效的id_token并完成签名校验(见下一节),两者存在时间差与失败可能。
技能的通用文档 SKILL.md 给出的建议是:使用 Convex 提供的认证感知 UI 组件(如Authenticated、Unauthenticated、AuthLoading)或useConvexAuth()hook 来门控 UI,确保在 Convex 确认会话之前,受保护界面不渲染。
后端函数保护:ctx.auth.getUserIdentity()
UI 层门控只是体验层面,真正的安全边界在后端函数。后端保护的标准模式(同样来自 SKILL.md 与源码佐证)是绝不信任客户端传入的 userId,而是在每个受保护函数内通过ctx.auth.getUserIdentity()校验身份:
// 错误示范:信任客户端传入的 userId export const getMyProfile = query({ args: { userId: v.id("users") }, handler: async (ctx, args) => { return await ctx.db.get(args.userId); }, }); // 正确示范:服务端验证身份 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(); }, });关于getUserIdentity()的返回结构,server/authentication.ts 中定义了UserIdentity接口,其中唯一保证存在的字段是tokenIdentifier(由 JWT 的sub+iss拼接而成,全局稳定唯一)与issuer,其余 OIDC 标准字段(如subject、name、email等)是否出现取决于 Auth0 返回的声明内容;此外还可通过类型断言读取 Auth0 JWT 中的自定义声明(custom claims)。在 Convex 后端(Rust 侧)中,这一身份校验通过 isolate 运行时提供的 syscall 实现(参见 crates/isolate/src/environment/udf/async_syscall.rs 中的相关 syscall 处理),整个令牌解析与校验发生在服务端,客户端无法伪造。
是否创建应用级users表取决于应用是否需要把用户文档存入 Convex。文档明确:并非每个应用都需要users表,只有确实需要在 Convex 中保存用户文档时才添加,且不要为 Auth0 这类第三方提供方机械照搬"跨提供方 users 表 + storeUser 流程"。
完整接入步骤清单
综合原文档的 Workflow 与 Concrete Steps,一份可执行的总步骤清单如下:
- 确认用户确实要 Auth0(而非其他提供方);
- 确认应用框架,检查 Auth0 是否已部分接入;
- 询问 local-only 还是 production-ready;
- 阅读官方 Convex Auth0 文档与对应框架的 Auth0 quickstart(本地参考见 docs/auth/auth0.mdx);
- 询问用户是否接受 Auth0 CLI 最快路径;若同意,安装 CLI 并要求用户
auth0 login; - 若走 CLI:用
auth0 apps create创建 SPA 应用(含 callback URL、logout URL、web origins),机械性设置在 CLI 中完成;若走 Dashboard:完成前端 quickstart 并手动创建应用; - 从 CLI 输出或 Dashboard 获取 Auth0 domain 与 client ID;
- 为应用框架安装 Auth0 SDK;
- 创建或更新
convex/auth.config.ts,填入 Auth0 domain 与 client ID; - 设置前端与后端环境变量(
AUTH0_DOMAIN、AUTH0_CLIENT_ID、VITE_AUTH0_DOMAIN、VITE_AUTH0_CLIENT_ID等); - 用
Auth0Provider包裹应用; - 将原有纯
ConvexProvider接线替换为ConvexProviderWithAuth0; - 修改后端配置后,运行正常的 Convex dev 或 deploy 流程让后端同步配置;
- 用 Convex 认证状态门控受保护 UI;
- 验证登录后 Convex 报告用户已认证;
- 若为生产配置,单独覆盖生产 Auth0 租户值、回调地址与生产环境变量。
验证清单与失败处置
原文档给出了严格的验证要求,核心原则是:"Auth0 登录成功"与"Convex 能校验 Auth0 令牌"是两件事,必须同时成立。验证清单如下:
- 用户能完成 Auth0 登录流程;
- Convex 认证状态的 UI 仅在 Convex auth state 就绪后渲染;
- 登录后受保护的 Convex query 能成功执行;
- 受保护后端函数中
ctx.auth.getUserIdentity()返回非 null; - 开发期间 Auth0 应用设置与本地真实 callback、logout URL 匹配;
- 若请求了生产配置,生产 Auth0 配置同样被覆盖。
失败处置原则(重要):文档多次强调,如果 Auth0 登录或刷新链路出现文档无法明确解释的失败(例如Unknown or invalid refresh token错误),停止自行猜测修复,明确告知用户该路径仍在调查中(under investigation),并把用户引导回官方文档手动完成。绝不能为了"完成任务"而谎称流程已验证。
特别是 refresh-token 路径:文档记录,在验证中按照官方文档配置useRefreshTokens={true}与cacheLocation="localstorage"时遭遇了刷新令牌失败,因此不应把该路径描述为已定论;对应地,ConvexProviderWithAuth0 的实现 默认依赖getAccessTokenSilently的静默刷新机制,实际表现应结合 Auth0 应用设置与租户策略实测验证。
生产环境配置
若用户要求 production-ready 配置,在宣布任务完成前必须确认:
- 生产 Auth0 租户的 domain、client ID 与回调地址是否已覆盖;
- 生产环境变量与 redirect 设置是否核验;
- 若开发与生产使用不同 Auth0 租户,两者配置各自独立、互不混用。
另外,除非用户明确要求,不要默认在仓库中写入笔记或交接文档;如需产出 rollout 或 handoff 文档,应先征得用户同意再创建。
常见陷阱(Gotchas)速查
- 不要跳过 Auth0 前端 quickstart——Convex 官方文档假设 Auth0 侧已就绪;
- Auth0 CLI 最快但非完全验证路径,仍需用户完成
auth0 login认证 CLI; - 用户同意安装 CLI 后,机械性设置由自己完成,不要又把用户推回 Dashboard;
- 登录成功但 Convex 仍报未认证时,先检查
convex/auth.config.ts与后端配置是否已同步(重跑 dev/deploy); - 不要混淆"Auth0 登录可用"与"Convex 能校验 Auth0 令牌";
- 仓库已用 Auth0 时,保留既有 redirect 与租户配置;
- 不要假设本地租户设置与生产一致,生产 domain、client ID、回调地址单独核验;
- 本地开发时 Auth0 应用设置必须匹配真实端口;
- 遇到刷新令牌类错误不要无限试错,退回官方文档并向用户说明现状。
总结
Auth0 与 Convex 的集成由三条主线构成:Auth0 侧的 SPA 应用与回调配置(CLI 或 Dashboard 路径)、Convex 侧的令牌校验配置(convex/auth.config.ts的domain+applicationID)、前端接线(Auth0Provider→ConvexProviderWithAuth0→ Convex 认证状态门控 UI + 后端ctx.auth.getUserIdentity()保护)。验证时必须同时确认 Auth0 登录与 Convex 会话识别都成功,而对尚未验证的 refresh-token 路径应保持诚实、以官方文档为准。
- 数据库
- 后端
【免费下载链接】convex-backend
The open-source reactive database for app developers
相关推荐
Redwood 集成 Auth0 认证:从环境变量配置到 JWT 验证的完整实战指南
Redwood 集成 Auth0 认证:从环境变量配置到 JWT 验证的完整实战指南 Auth0 是 Redwood 官方提供的一等公民集成方案,通过 @red
后端前端Web框架开发工具在 RedwoodJS 中集成 Auth0 认证:从控制台配置到 JWT 验证的完整实战
在 RedwoodJS 中集成 Auth0 认证:从控制台配置到 JWT 验证的完整实战 本篇技术指南以 RedwoodJS 官方文档的 Auth0 认证章节为
后端前端Web框架开发工具TDengine PI 数据接入:连接配置与 Windows 集成认证完全指南
TDengine PI 数据接入:连接配置与 Windows 集成认证完全指南 PI(OSIsoft PI System)是电力、石化、制造等行业广泛使用的实时
数据库时序数据库物联网大数据实时分析云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考