用途
express-oauth2-jwt-bearer 是 Auth0 提供的 Express 中间件,用于校验 Auth0 JWT Bearer 访问令牌。它按 RFC 6750 处理令牌提取、签名验证、受众(audience)与签发者(issuer)校验以及过期检查,让开发者专注于业务逻辑而非 JWT 解析。
主要能力
- JWT Bearer 令牌校验中间件 auth(),令牌无效或缺失时返回 401。
- 基于 scope 的访问控制:requiredScopes() 校验令牌是否包含全部所需 scope(缺失返回 403);scopeIncludesAny() 校验是否至少包含一个 scope。
- 基于 claim 的校验:claimEquals()、claimIncludes()、claimCheck()(自定义校验函数)。
- 支持 DPoP 绑定(通过 dpop 配置项)。
- 校验成功后,req.auth 包含 payload(解码后的 JWT 载荷,如 sub、iss、aud、exp、permissions 等)、header(alg、typ、kid)和 token(原始 JWT 字符串)。
- SDK 自动从环境变量 ISSUER_BASE_URL 和 AUDIENCE 读取配置,auth() 无需传参。
使用方式
前置条件:Node.js 18+(推荐 20+,bootstrap 脚本自动化需要 20+)、Express 4.x 或 5.x、npm 或 yarn、已配置 API(Resource Server)的 Auth0 账户;自动设置需 Auth0 CLI(npm install -g @auth0/auth0-cli)。
安装:
npm install express-oauth2-jwt-bearer
配置 .env:
ISSUER_BASE_URL=https://your-tenant.us.auth0.com
AUDIENCE=https://your-api-identifier
加载并应用中间件:
import 'dotenv/config'; // load .env before the SDK reads process.env
import { auth } from 'express-oauth2-jwt-bearer';
// Reads ISSUER_BASE_URL and AUDIENCE from the environment — no config needed
const checkJwt = auth();
app.use(checkJwt); // apply globally, or per-route
保护端点(全局或按路由):
// Global protection
app.use(checkJwt);
// Or per-route
app.get('/api/private', checkJwt, (req, res) => {
res.json({ sub: req.auth.payload.sub });
});
添加 RBAC(可选):
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 # should return 401
curl -H "Authorization: Bearer <token>" http://localhost:3000/api/private # should return 200
配置选项
- issuerBaseURL(string):带 https:// 的完整签发者 URL。可选,默认取 ISSUER_BASE_URL 环境变量。
- audience(string):Auth0 Dashboard 中的 API Identifier。可选,默认取 AUDIENCE 环境变量。
- tokenSigningAlg(string):签名算法,默认 RS256;对称算法用 HS256。
- authRequired(boolean):设为 false 使认证可选,默认 true。
- clockTolerance(number):时钟偏差容忍秒数,无默认值。
- dpop(DPoPOptions):DPoP 配置。
环境变量:ISSUER_BASE_URL(带 https:// 的完整签发者 URL,SDK 自动识别)、AUDIENCE(API Identifier,SDK 自动识别)。
适用场景
适用于由 SPA、移动应用、M2M 客户端调用的无状态 API。不适用于:带登录 UI 的服务端 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;Go API 应使用 go-jwt-middleware;Python API(Flask/FastAPI)应使用 auth0-api-python;使用旧版 express-jwt 包的 Node.js API 应使用 express-jwt。
限制与常见错误
- 在 Auth0 Dashboard 创建了 Application 而非 API:令牌校验失败、受众错误。应在 Auth0 Dashboard → APIs 创建新的 API(Resource Server)。
- 受众与 API Identifier 不完全匹配:401 Unauthorized — "Audience mismatch"。应复制 Auth0 Dashboard → APIs 中精确的 API Identifier 字符串。
- ISSUER_BASE_URL 缺少 https:// 协议:启动时报 Error: Invalid URL。ISSUER_BASE_URL 必须是完整签发者 URL。
- RBAC 检查 scope claim 而非 permissions:始终返回 403 或忽略权限。scope 用 requiredScopes(),Auth0 RBAC 权限 claim 用 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 为 undefined:TypeError: Cannot read properties of undefined。应确认 checkJwt 中间件在处理器之前运行。
SDK 架构
node-oauth2-jwt-bearer 单仓库包含三个包:express-oauth2-jwt-bearer(主包,Express 中间件,发布到 npm)、access-token-jwt(底层 JWT 验证工具,内部使用)、oauth2-bearer(RFC 6750 Bearer 令牌提取,内部使用)。实际只需安装并导入 express-oauth2-jwt-bearer。
测试参考
从 Auth0 Dashboard → APIs → 你的 API → Test 标签页获取测试令牌,然后:
# 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"
相关技能
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 的 JWT 校验,Flask/FastAPI)、auth0-cli(从终端管理 Auth0 资源)。