news 2026/9/23 23:57:32

在 Convex 中接入 Auth0 认证:从 Auth0 CLI 快速搭建到 Convex 后端验签的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Convex 中接入 Auth0 认证:从 Auth0 CLI 快速搭建到 Convex 后端验签的完整指南
  • 数据库
  • 后端

【免费下载链接】convex-backend

The open-source reactive database for app developers

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

导读

本指南围绕 Convex 开源仓库中 Auth0 认证接入的完整方案展开,覆盖"Auth0 应用创建(CLI 或 Dashboard 两条路径)→convex/auth.config.ts服务端配置 → 前后端环境变量 →Auth0Provider+ConvexProviderWithAuth0前端接线 → 用 Convex 认证状态门控 UI → 本地/生产双租户 → 验证与排障"的全流程。读完本文,你将掌握:如何用 Auth0 CLI 把机械化的应用创建自动化掉、如何让 Convex 后端独立校验 Auth0 签发的 JWT、为什么"Auth0 登录成功"不等于"Convex 认证通过",以及当 refresh token 流程报Unknown or invalid refresh token时该如何止损。

背景:为什么要在 Convex 项目里接入 Auth0

Auth0 是一个成熟的认证平台,提供密码登录、社交身份提供商(Google、GitHub 等)登录、一次性邮箱/短信验证码、多因素认证(MFA)、单点登录(SSO)以及基础用户管理能力。对于已经使用 Auth0、或明确指定要使用 Auth0 的 Convex 应用,将其作为认证层接入是最自然的选择。

在 Convex 的认证模型中,认证与授权是解耦的:Auth0 负责"确认你是谁"(签发 JWT),Convex 负责"验证你带来的 token 是否可信"(服务端校验签名与 audience,并给出UserIdentity)。因此整个接入工作可以分为两个互相独立、缺一不可的环节:

  1. Auth0 侧:创建 Auth0 应用、配置回调地址、让用户完成登录;
  2. Convex 侧:在convex/auth.config.ts中登记 Auth0 的domainapplicationID,让后端能够校验 Auth0 签发的 token。

参考官方文档见 npm-packages/docs/docs/auth/auth0.mdx,本文以该指南与 npm-packages/private-demos/waitlist/.claude/skills/convex-setup-auth/references/auth0.md(下文简称"技能参考文档")为骨架展开。

接入前的决策点

动手之前,技能参考文档明确要求先确认三件事:

  1. 确认用户确实想要 Auth0,而不是其他认证方案;
  2. 确认应用的技术栈(React / Next.js / Vite 等)以及 Auth0 是否已经部分接入——如果仓库里已经有 Auth0 配置,务必保留既有的 redirect 与 tenant 配置,除非用户明确要求改动;
  3. 确认本次只做本地(local-only)还是要做生产就绪(production-ready),这决定了后续是只配置 dev tenant,还是 dev/prod 双 tenant 都要覆盖。

此外还要决定走哪条创建路径

  • Auth0 CLI 路径:最快,适合从零开始的新项目。先安装 Auth0 CLI,用户执行一次auth0 login完成 CLI 与自身 Auth0 tenant 的绑定,之后应用创建、回调 URL 配置等机械操作都可以自动化完成;
  • Dashboard 路径:不安装任何额外工具,在 Auth0 控制台手动创建应用,适合不愿意安装 CLI 或已有存量应用的场景。

技能参考文档特别强调:不要假装 refresh-token 路径已经被完整验证。仓库内的验证记录显示,useRefreshTokens={true}配合cacheLocation="localstorage"的官方推荐配置在实际验证中曾触发 refresh-token 失败,因此该路径目前仍标记为"under investigation",遇到相关报错时应明确告知用户并引导回官方文档,而不是无限自行修补。

第一条路径:用 Auth0 CLI 快速创建应用

如果用户同意安装 Auth0 CLI,按以下步骤执行(Auth0 CLI 的安装与命令参考见其官方文档auth0-apps-create页面):

# 1. 安装并登录(登录需要用户本人的 Auth0 账号交互) auth0 login # 2. 创建 SPA 应用:指定应用类型、回调地址、登出地址与 Web 来源 auth0 apps create \ --type spa \ --callback-urls "http://localhost:5173/callback" \ --logout-urls "http://localhost:5173" \ --web-origins "http://localhost:5173"

创建完成后,从 CLI 输出中取回两项关键信息:Auth0 domain(形如your-domain.us.auth0.com)和client ID。它们将同时用于后端auth.config.ts与前端Auth0Provider

需要特别注意的是:CLI 路径虽然快,但仍然要求用户先把 CLI 认证到自己的 Auth0 tenant;并且 CLI 产出的只是 Auth0 应用侧的配置,Convex 侧的接线仍然需要手工完成。技能参考文档的定位是"优先 CLI 做机械搭建,但不要把该路径描述为端到端已验证"。

第二条路径:Auth0 Dashboard 手动创建

不走 CLI 时,按 Auth0 官方 React Quickstart 在 Dashboard 中创建应用:

  1. 注册免费 Auth0 账号并创建 tenant;
  2. 在 Dashboard 的 Applications 中新建Single Page Application(SPA)
  3. 配置回调地址(Callback URLs)、登出地址(Logout URLs)与 Allowed Web Origins。官方文档给出的本地开发示例值为http://localhost:3000, http://localhost:5173,具体以你本地实际运行的端口为准——回调/登出/Web Origins 必须与开发服务器真实端口完全一致,否则登录跳转会失败;
  4. 完成 Auth0 React Quickstart 中"Install the Auth0 React SDK"这一步后,即可回到 Convex 侧接线。

技能参考文档的 Gotchas 提醒:Convex 官方文档默认 Auth0 侧已经就绪,所以从零开始的项目不要跳过 Auth0 quickstart;同时不要想当然地认为本地 tenant 的配置与生产一致,生产环境的 domain、client ID 和回调 URL 都需要单独核实。

配置 Convex 后端:convex/auth.config.ts

在项目convex/目录下创建auth.config.ts,把 Auth0 的 domain 与 client ID 填入:

import { AuthConfig } from "convex/server"; export default { providers: [ { domain: "your-domain.us.auth0.com", applicationID: "yourclientid", }, ] } satisfies AuthConfig;

从源码看,AuthConfigAuthProvider的类型定义位于 npm-packages/convex/src/server/authentication.ts:

  • providers是允许为你的应用签发 JWT 的认证提供方列表;
  • OIDC 提供方(Auth0 属于此类)需要domain(OIDC 提供方的域名)与applicationID
  • 后端校验时要求token 的 audience 中包含该applicationIDapplicationID匹配不上会导致认证失败;
  • 除 OIDC 外该类型还支持customJwt提供方(需配置issuerjwks地址与RS256/ES256签名算法),Auth0 接入不需要用到。

关键操作:修改auth.config.ts后必须重新同步到后端,否则后端仍按旧配置校验:

npx convex dev # 本地开发,自动同步配置到后端

生产环境则使用npx convex deploy

前端接线:Auth0Provider 与 ConvexProviderWithAuth0

前端需要安装 Auth0 SDK(React 项目为@auth0/auth0-react),然后把原本的ConvexProvider替换为「Auth0Provider包裹ConvexProviderWithAuth0」的结构。ConvexProviderWithAuth0的完整实现位于 npm-packages/convex/src/react-auth0/ConvexProviderWithAuth0.tsx,源码揭示了几点关键事实:

  • 它内部通过useAuth0()取得isLoadingisAuthenticatedgetAccessTokenSilently
  • 取 token 时调用getAccessTokenSilently({ detailedResponse: true, cacheMode: forceRefreshToken ? "off" : "on" }),并返回id_token而非 access token——Convex 用它作为 JWT 交给后端验签;
  • 它基于通用的 npm-packages/convex/src/react/ConvexAuthState.tsx 中的ConvexProviderWithAuth实现:认证状态由Auth0 前端状态Convex 后端确认结果双重决定——isAuthenticated = authProviderAuthenticated && (isConvexAuthenticated ?? false),即只有 Auth0 已登录且 Convex 后端确认 token 有效,才算真正认证通过;
  • useConvexAuth()会返回isLoading/isAuthenticated/isRefreshing三个状态,其中isRefreshing表示后端拒绝了此前已确认的 token、socket 暂停等待新 token(仅在isAuthenticated为 true 时可能出现)。

仓库中的真实示例(npm-packages/private-demos/quickstarts/react-vite-ts/src/_mainAuth0.tsx)展示了完整的接线方式:

import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import "./index.css"; import { ConvexReactClient } from "convex/react"; import { ConvexProviderWithAuth0 } from "convex/react-auth0"; import { Auth0Provider } from "@auth0/auth0-react"; const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string); ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <Auth0Provider domain="your-domain.us.auth0.com" clientId="yourclientid" authorizationParams={{ redirect_uri: window.location.origin, }} useRefreshTokens={true} cacheLocation="localstorage" > <ConvexProviderWithAuth0 client={convex}> <App /> </ConvexProviderWithAuth0> </Auth0Provider> </React.StrictMode>, );

需要说明的是:useRefreshTokens={true}cacheLocation="localstorage"是官方示例的推荐写法,但按照技能参考文档的验证记录,该 refresh-token 组合在实际验证中触发过失败(详见"验证与已知问题"一节),因此接入时如遇相关报错,不应将其视为已定论的配置。

登录、登出与用户信息

登录与登出按钮

登录与登出使用 Auth0 React SDK 的useAuth0()hook:

import { useAuth0 } from "@auth0/auth0-react"; export default function LoginButton() { const { loginWithRedirect } = useAuth0(); return <button onClick={loginWithRedirect}>Log in</button>; }

loginWithRedirect会把用户重定向到 Auth0 Universal Login 页面;登出则调用logout()重定向到 Auth0 登出端点。

用 useConvexAuth 门控 Convex 相关 UI

判断"Convex 数据是否可安全展示"时,不要用useAuth0(),要用useConvexAuth():它保证浏览器已经取到访问 Convex 后端所需的 token:

import { useConvexAuth } from "convex/react"; function App() { const { isLoading, isAuthenticated } = useConvexAuth(); return ( <div className="App"> {isAuthenticated ? "Logged in" : "Logged out or still loading"} </div> ); }

也可以使用AuthenticatedUnauthenticatedAuthLoadingAuthRefreshing四个声明式组件(它们底层都基于useConvexAuth),其中AuthRefreshing在查询/变更因 token 刷新被暂停时渲染(通常是罕见场景):

import { Authenticated, Unauthenticated, AuthLoading, AuthRefreshing, } from "convex/react"; function App() { return ( <div className="App"> <Authenticated>Logged in</Authenticated> <Unauthenticated>Logged out</Unauthenticated> <AuthLoading>Still loading</AuthLoading> <AuthRefreshing>Refreshing token...</AuthRefreshing> </div> ); }

展示用户信息

前端展示用户昵称等信息直接用useAuth0()user对象:

import { useAuth0 } from "@auth0/auth0-react"; export default function Badge() { const { user } = useAuth0(); return <span>Logged in as {user.name}</span>; }

而后端函数(query/mutation/action)中获取用户身份则通过ctx.auth.getUserIdentity()——这是验证"Convex 是否认可该 Auth0 会话"的权威途径(见下文"验证")。

环境变量:本地与生产分离

后端环境变量

auth.config.ts改为读取环境变量,即可在 dev / prod 之间切换不同 Auth0 tenant:

import { AuthConfig } from "convex/server"; export default { providers: [ { domain: process.env.AUTH0_DOMAIN!, applicationID: process.env.AUTH0_CLIENT_ID!, }, ], } satisfies AuthConfig;
  • 本地开发:在 Convex Dashboard 的 dev deployment Settings → Environment Variables 中添加AUTH0_DOMAINAUTH0_CLIENT_ID,然后运行npx convex dev应用新配置;
  • 生产:在 Convex Dashboard 左侧菜单切换到生产 deployment,设置生产 Auth0 tenant 对应的值,然后运行npx convex deploy

前端环境变量

客户端侧同样用环境变量注入,变量名取决于前端平台(Vite 使用VITE_前缀)。本地开发写入.env.local

VITE_AUTH0_DOMAIN="your-domain.us.auth0.com" VITE_AUTH0_CLIENT_ID="yourclientid"

对应的Auth0Provider写法见仓库示例 npm-packages/private-demos/quickstarts/react-vite-ts/src/_mainAuth0Env.tsx:

<Auth0Provider domain={import.meta.env.VITE_AUTH0_DOMAIN} clientId={import.meta.env.VITE_AUTH0_CLIENT_ID} authorizationParams={{ redirect_uri: window.location.origin, }} useRefreshTokens={true} cacheLocation="localstorage" > <ConvexProviderWithAuth0 client={convex}> <App /> </ConvexProviderWithAuth0> </Auth0Provider>

生产环境则在你的托管平台上设置同名变量。技能参考文档总结的常见环境变量集为:

变量用途
AUTH0_DOMAIN/AUTH0_CLIENT_IDConvex 后端读取,写入 Convex Dashboard 环境变量
VITE_AUTH0_DOMAIN/VITE_AUTH0_CLIENT_IDVite 前端读取(其他框架前缀不同),写入.env.local或托管平台

保持 dev 与 prod tenant 分离:如果项目在不同环境使用不同的 Auth0 tenant,务必确认生产 domain、client ID、回调 URL 各自独立配置,不要默认本地 tenant 设置与生产一致。

验证:Auth0 登录成功 ≠ Convex 认证通过

技能参考文档的 Validation 章节给出了一套完整的验收清单:

  • 用户能完整走完 Auth0 登录流程(登录 → 重定向回应用);
  • Convex 认证状态的 UI 仅在useConvexAuth()的 auth state ready 后才渲染;
  • 登录后受保护的 Convex query 能正常执行;
  • 后端受保护函数中ctx.auth.getUserIdentity()返回非null
  • 开发期间 Auth0 应用设置与真实本地回调/登出 URL 一致;
  • 若请求了生产就绪配置,生产 Auth0 配置也已覆盖。

其中最关键的一条是后端视角的确认ctx.auth.getUserIdentity()非空,才意味着 Convex 后端真正验证了 Auth0 签发的 JWT(签名、issuer、audience 均通过)。技能参考文档特别警告:"Auth0 登录成功"与"Convex 能验证 Auth0 token"是两件不同的事,二者都必须成立——Auth0 侧成功只代表用户拿到了 Auth0 的会话,Convex 侧还需要 token 通过后端校验。

调试:登录成功但 isAuthenticated 为 false

如果用户走完 Auth0 登录、重定向回页面后useConvexAuth()仍返回isAuthenticated: false,按以下顺序排查:

  1. 检查convex/auth.config.tsdomainapplicationID是否与 Auth0 应用设置完全一致(domain 形如your-domain.us.auth0.com,client ID 可在 Auth0 Dashboard 的 Application Settings 中查到);
  2. 确认后端配置已同步auth.config.tsproviders列表必须通过npx convex dev(本地)或npx convex deploy(生产)同步到后端,只改文件不运行命令不会生效;
  3. 检查前端Auth0Providerdomain/clientId是否与后端配置一致,避免出现前端用 dev tenant、后端用 prod tenant 的错配;
  4. 确认本地回调 URL、登出 URL、Web Origins 与实际端口匹配。

更深入的排查步骤可参考仓库文档 npm-packages/docs/docs/auth/debug.mdx。

已知问题与诚实边界

技能参考文档在 Gotchas 中记录了几条尚未完全验证的边界,接入时务必知情:

  • refresh-token 路径未端到端验证:文档推荐并验证过的useRefreshTokens={true}+cacheLocation="localstorage"组合曾触发 refresh-token 失败,因此不要将该路径描述为"已定论";若遇到Unknown or invalid refresh token之类的 Auth0 报错,不要无限编造修复方案,应停止并向用户说明该路径仍在调查中,引导回官方文档;
  • CLI 路径未完全验证:Auth0 CLI 可以自动化应用创建与 Convex 配置接线,但它要求用户先将 CLI 认证到自己的 tenant,且该路径同样没有完成 refresh-token 的端到端验证;
  • 不要把"能登录"当"已验证":只有用户能登录Convex 识别该认证会话(getUserIdentity()非空)时,才能宣称接入成功;否则应如实标注"该路径仍在调查中";
  • 不要默认向仓库写笔记文件:如用户需要 rollout 或交接文档,应显式创建,而不是默认把 notes 文件静默写进仓库。

生产就绪收尾

如果用户要求 production-ready 配置,最终验收前确认:

  • 生产 Auth0 tenant 的值(domain、client ID)已配置到生产 Convex deployment 的环境变量;
  • 生产 Auth0 应用的回调 URL、登出 URL 与 Web Origins 指向真实生产域名;
  • 生产环境变量与重定向设置均已核实,再宣布任务完成。

完整检查清单

  • 确认用户确实想要 Auth0
  • 确认本地优先还是生产就绪
  • 完成对应框架的 Auth0 前端 quickstart(从零开始的项目不可跳过)
  • 配置convex/auth.config.ts(domain + applicationID)
  • 运行npx convex dev/npx convex deploy同步后端配置
  • 设置前后端环境变量(AUTH0_DOMAINAUTH0_CLIENT_IDVITE_AUTH0_DOMAINVITE_AUTH0_CLIENT_ID等)
  • Auth0Provider包裹ConvexProviderWithAuth0
  • useConvexAuth()/Authenticated等门控 Convex UI
  • 登录后验证useConvexAuth()为 authenticated,且后端ctx.auth.getUserIdentity()非空;否则明确告知该路径仍在调查中并引导官方文档
  • 如请求了生产配置,确认生产 tenant 与部署配置也已覆盖

参考源码与文档索引

  • 官方 Auth0 接入指南:npm-packages/docs/docs/auth/auth0.mdx
  • 前端适配组件实现:npm-packages/convex/src/react-auth0/ConvexProviderWithAuth0.tsx
  • 通用认证状态机制:npm-packages/convex/src/react/ConvexAuthState.tsx
  • 后端配置类型定义(AuthConfig/AuthProvider/UserIdentity):npm-packages/convex/src/server/authentication.ts
  • 硬编码配置示例:npm-packages/private-demos/quickstarts/react-vite-ts/src/_mainAuth0.tsx
  • 环境变量配置示例:npm-packages/private-demos/quickstarts/react-vite-ts/src/_mainAuth0Env.tsx
  • 认证调试指南:npm-packages/docs/docs/auth/debug.mdx
  • 数据库
  • 后端

【免费下载链接】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 23:57:14

OpenSpec:规范驱动开发(Spec-Driven)的契约编译器与双向同步实践

1. OpenSpec 是什么&#xff1f;它不是另一个 CLI 工具&#xff0c;而是一套重构开发流程的 Spec 驱动范式OpenSpec 不是 npm 上随便一个带“open”前缀的玩具库&#xff0c;也不是某个公司包装出来的营销概念。我第一次在 Fission AI 的技术分享会上听到它时&#xff0c;主讲人…

作者头像 李华
网站建设 2026/9/23 23:54:07

C#接入百度OCR:从Token缓存到高精度图像识别的完整实现

简介&#xff1a;这是一份基于 C# 调用百度 OCR 接口的图像文字识别示例工程包&#xff0c;面向需要在 Windows 桌面应用中快速集成文字识别能力的开发者&#xff0c;尤其适合入门到中级 C# 程序员作为 AI 接口调用练手项目。资源重点演示了申请百度 AI 开放平台 API 密钥、构造…

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

STM32 IAP Ymodem上位机:C#轻量客户端实现与协议详解

简介&#xff1a;这是一份面向嵌入式开发工程师与STM32进阶学习者的IAP固件升级实战资源&#xff0c;聚焦C#上位机与STM32端协同实现Ymodem协议驱动的远程固件更新。资源提供完整可运行的Windows客户端工程&#xff0c;涵盖串口通信管理、Ymodem协议封装&#xff08;含128字节块…

作者头像 李华
网站建设 2026/9/23 23:46:52

从SR1、DFP到BFGS:拟牛顿法更新公式对比与选型指南

1. 从牛顿法到拟牛顿法&#xff1a;为什么需要这条演进路线很多人第一次接触优化算法&#xff0c;都是从梯度下降开始的。梯度下降简单、直观&#xff0c;沿着梯度的反方向走一步&#xff0c;步长靠学习率控制。但用久了就会发现一个问题&#xff1a;它在不同方向上的收敛速度差…

作者头像 李华