关于 express-oauth2-jwt-bearer
为 Node.js Express API 提供 Auth0 JWT Bearer 令牌验证中间件的集成技能,可校验签名、受众、发行者和有效期。还支持按 scope 或声明限制路由访问。
主要功能
- 01验证 Bearer JWT 令牌
- 02校验签名、受众和发行者
- 03检查令牌有效期
- 04按 scope 限制访问
- 05按声明执行授权检查
适用场景
- 01保护 Express API 路由
- 02验证 SPA 或移动端发来的访问令牌
- 03按 scope 控制 API 权限
- 04按令牌声明限制请求
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ auth0/ agent-skills --skill express-oauth2-jwt-bearer安装后在 Claude Code 中输入/express-oauth2-jwt-bearer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api.mdintegration.mdsetup.mdscripts/bootstrap.mjspackage.jsonscripts/utils/apis.mjsauth0-api.mjschange-plan.mjsdiscovery.mjsenv-writer.mjshelpers.mjsvalidation.mjstests/evals.jsongraders.jsonprompt.md详细介绍
Node OAuth2 JWT Bearer 集成
express-oauth2-jwt-bearer 包提供 Express 中间件,用于验证 Auth0 JWT Bearer 访问令牌。它会处理令牌提取、签名验证、受众和颁发者验证以及过期检查,遵循 RFC 6750,让你专注于业务逻辑,而不必解析 JWT。
Agent 指令: 在提供 SDK 设置说明之前,请运行以下命令获取最新发布版本:
gh api repos/auth0/node-oauth2-jwt-bearer/releases/latest --jq '.tag_name'在所有
package.json依赖项声明中使用返回的版本,而不是下方任何硬编码的版本。
先决条件
- Node.js 18+(推荐使用 20+;自动化引导脚本需要此版本)
- Express 4.x 或 5.x
- npm 或 yarn
- 已配置 API(资源服务器)的 Auth0 账户
- Auth0 CLI(用于自动设置):
npm install -g @auth0/auth0-cli
不适用场景
| 使用场景 | 推荐技能 |
|---|---|
| 构建带有登录界面的服务端 Web 应用(Express 会话) | auth0-express |
| 构建具有服务端身份验证功能的 Next.js 应用 | auth0-nextjs |
| 构建 React/Angular/Vue SPA | auth0-react、auth0-angular、auth0-vue |
| 构建 React Native 或移动应用 | auth0-react-native、auth0-android、auth0-swift |
| ASP.NET Core Web API | auth0-aspnetcore-api |
| 使用 JWT 中间件的 Go API | go-jwt-middleware |
| Python API(Flask/FastAPI) | auth0-api-python |
使用旧版 express-jwt 包的 Node.js API | express-jwt |
快速入门工作流
Agent 指令: 按照以下步骤将
express-oauth2-jwt-bearer集成到用户的 Node.js API 项目中。
获取最新版本(参见上方说明)。
安装 SDK:
npm install express-oauth2-jwt-bearer配置 Auth0 — 按照
references/setup.md操作。如果用户已在提示词中提供 Auth0 Domain 和 API Audience,请将其写入.env文件,分别设为ISSUER_BASE_URL(完整的 issuer URL,包括https://)和AUDIENCE— SDK 会自动读取这些值。跳过引导脚本,不要调用AskUserQuestion再次确认。绝不要在server.js/app.js中将 domain 或 audience 硬编码为字面字符串(或||回退默认值) — 它们只能放在.env中。否则,可提供通过引导脚本自动设置或手动设置的选项。设置中间件 — 先创建包含 Auth0 值的
.env文件,然后加载它并添加中间件。express-oauth2-jwt-bearer会自动从环境中读取ISSUER_BASE_URL和AUDIENCE,因此auth()无需参数:# .env ISSUER_BASE_URL=https://your-tenant.us.auth0.com AUDIENCE=https://your-api-identifierimport 'dotenv/config'; // 在 SDK 读取 process.env 之前加载 .env import { auth } from 'express-oauth2-jwt-bearer'; // 从环境中读取 ISSUER_BASE_URL 和 AUDIENCE — 无需配置 const checkJwt = auth(); app.use(checkJwt); // 全局应用,或按路由应用将 issuer 和 audience 保存在
.env中 — 不要在此处内联字面值或将它们作为参数传入。保护端点 — 全局应用中间件或将其应用到特定路由:
// 全局保护 app.use(checkJwt); // 或按路由应用 app.get('/api/private', checkJwt, (req, res) => { res.json({ sub: req.auth.payload.sub }); });添加 RBAC(可选)— 使用
requiredScopes()或claimIncludes()实现基于权限的访问控制:import { auth, requiredScopes, claimIncludes } from 'express-oauth2-jwt-bearer'; app.get('/api/messages', checkJwt, requiredScopes('read:messages'), (req, res) => { res.json({ messages: [] }); });重要:
requiredScopes接受单个参数 — 以空格分隔的字符串或数组。不要传入多个字符串参数:requiredScopes('read:msg', 'write:msg')会静默忽略第一个参数之后的所有内容。请改用requiredScopes('read:msg write:msg')或requiredScopes(['read:msg', 'write:msg'])。验证集成 — 构建并测试:
node server.js curl http://localhost:3000/api/private # 应返回 401 curl -H "Authorization: Bearer <token>" http://localhost:3000/api/private # 应返回 200故障检查: 如果服务无法启动或令牌意外遭到拒绝,请查看
references/api.md了解常见问题。连续 5-6 次迭代失败后,使用AskUserQuestion询问用户更多环境详情。
详细文档
- 设置指南 — Auth0 API 注册、.env 配置、自动设置引导脚本和密钥管理
- 集成模式 — 受保护端点、基于 scope 和 claim 的 RBAC、DPoP、CORS 设置、错误处理以及使用 curl 进行测试
- API 参考与测试 — 完整配置选项、claim 参考、完整代码示例、测试清单和常见问题
常见错误
| 错误 | 症状 | 修复方法 |
|---|---|---|
| 在 Auth0 Dashboard 中创建了 Application,而不是 API | 令牌验证失败;audience 错误 | 在 Auth0 Dashboard → APIs 中创建新的 API(Resource Server) |
| Audience 与 API 标识符不完全一致 | 401 Unauthorized — “Audience mismatch” | 从 Auth0 Dashboard → APIs 复制准确的 API Identifier 字符串 |
ISSUER_BASE_URL 缺少 https:// 协议 | 启动时出现 Error: Invalid URL | ISSUER_BASE_URL 必须是完整的发行者 URL:https://your-tenant.us.auth0.com |
RBAC 检查的是 scope 声明,而不是 permissions | 始终返回 403,或权限被忽略 | 对基于 scope 的 RBAC 使用 requiredScopes();对 Auth0 RBAC 权限声明使用 claimIncludes('permissions', 'read:data') |
| 在认证中间件之前未配置 CORS | 预检 OPTIONS 请求返回 401 | 在中间件链中,将 cors() 中间件添加到 auth() 之前 |
未加载 .env 文件 | domain/audience 为 undefined | 在入口文件顶部添加 import 'dotenv/config' |
在源码中硬编码 domain/audience(包括 process.env.X || 'literal' 回退值) | 密钥被提交到源码中;安全审查无法通过 | 将值放入 .env(ISSUER_BASE_URL / AUDIENCE),并让 auth() 自动读取——不要使用字面量回退值 |
req.auth 未定义 | TypeError: Cannot read properties of undefined | 确认 checkJwt 中间件在处理程序之前运行 |
相关技能
- auth0-express — 适用于带有登录 UI 的 Express Web 应用(会话、Cookie)
- auth0-nextjs — 适用于 Next.js 服务端 Web 应用
- auth0-aspnetcore-api — .NET 的 BACKEND_API 参考实现
- go-jwt-middleware — 适用于 Go API 的 JWT 中间件
- auth0-api-python — 适用于 Python API(Flask/FastAPI)的 JWT 验证
- auth0-cli — 从终端管理 Auth0 资源
快速参考
核心中间件
| 函数 | 描述 | 返回值 |
|---|---|---|
auth(options?) | JWT Bearer 验证中间件 | Handler — 令牌无效或缺失时返回 401 |
requiredScopes(scopes) | 验证令牌是否包含所有必需的 scopes | Handler — scopes 缺失时返回 403 |
scopeIncludesAny(scopes) | 验证令牌是否至少包含一个 scope | Handler — 不匹配时返回 403 |
claimEquals(claim, value) | 验证声明是否等于指定值 | Handler — 不匹配时返回 401 |
claimIncludes(claim, ...values) | 验证声明是否包含所有指定值 | Handler — 不完整时返回 401 |
claimCheck(fn, desc?) | 自定义声明验证函数 | Handler — fn 返回 false 时返回 401 |
配置选项
| 选项 | 类型 | 描述 |
|---|---|---|
issuerBaseURL | string | 带有 https:// 的完整发行者 URL。可选 — 默认使用 ISSUER_BASE_URL 环境变量 |
audience | string | Auth0 Dashboard 中的 API Identifier。可选 — 默认使用 AUDIENCE 环境变量 |
tokenSigningAlg | string | 签名算法(默认值:RS256;对称签名时使用 HS256) |
authRequired | boolean | 设为 false 以使认证变为可选(默认值:true) |
clockTolerance | number | 时钟偏差容差,单位为秒(无默认值;未设置时为 undefined) |
dpop | DPoPOptions | DPoP 配置(参见 integration.md) |
环境变量
| 变量 | 描述 |
|---|---|
ISSUER_BASE_URL | 带有 https:// 的完整发行者 URL,例如 https://your-tenant.us.auth0.com(SDK 自动检测) |
AUDIENCE | API Identifier,例如 https://your-api-identifier(SDK 自动检测) |
请求对象
验证成功后,req.auth 包含:
req.auth.payload // Decoded JWT payload (sub, iss, aud, exp, permissions, etc.)
req.auth.header // JWT header (alg, typ, kid)
req.auth.token // Raw JWT string
SDK 架构
node-oauth2-jwt-bearer monorepo 包含三个包:
| 包 | 用途 |
|---|---|
express-oauth2-jwt-bearer | 主包。 用于验证 JWT Bearer 的 Express 中间件。发布到 npm。 |
access-token-jwt | 低级 JWT 验证工具(内部使用)。 |
oauth2-bearer | 用于提取 RFC 6750 Bearer 令牌(内部使用)。 |
实际使用时,只需安装并导入 express-oauth2-jwt-bearer。
身份验证流程对比
| 身份验证模式 | SDK | 适用场景 |
|---|---|---|
| JWT Bearer(无状态) | express-oauth2-jwt-bearer | 由 SPA、移动应用、M2M 客户端调用的 API |
| 基于会话(有状态) | @auth0/express-openid-connect | 带有登录界面和服务端会话的 Web 应用 |
测试速查
# Get test token from Auth0 Dashboard → APIs → your API → Test tab
# Copy the token, then:
# 1. Verify 401 on protected route (no token)
curl -v http://localhost:3000/api/private
# 2. Verify 200 with valid token
curl -H "Authorization: Bearer <paste-token-here>" http://localhost:3000/api/private
# 3. Verify 403 with valid token but missing scope
curl -H "Authorization: Bearer <paste-token-here>" http://localhost:3000/api/admin
# 4. Verify CORS preflight
curl -v -X OPTIONS http://localhost:3000/api/private \
-H "Origin: http://localhost:5173" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: Authorization"