跳到主要内容
ecdsa.com
express-jwt (Node.js)JWT 库

错误信息

UnauthorizedError: No authorization token was found

也可能输出为

  • No authorization token was found
  • Format is Authorization: Bearer [token]

如果不处理这个错误,Express 会连同堆栈一起打印它,开头是“UnauthorizedError: No authorization token was found”。`err.code` 用来区分 `credentials_required`(没有令牌)与 `credentials_bad_scheme` 和 `credentials_bad_format`(“Format is Authorization: Bearer [token]”)。

express-jwt (Node.js) — UnauthorizedError, code credentials_required

含义

express-jwt 保护着这个路由,但没有找到令牌:请求中没有 `Authorization` 头,也没有自定义的 `getToken` 函数返回令牌。由于 `credentialsRequired` 默认为 `true`,中间件会抛出带有 `code: "credentials_required"` 和 `status: 401` 的 `UnauthorizedError`,请求永远到达不了你的处理函数。如果请求头存在、但格式不是 `Bearer <token>`,报出的则是“Format is Authorization: Bearer [token]”。

原因

修复方法

  1. 1.

    告诉 express-jwt 令牌在哪里

    `getToken` 接收请求,返回令牌字符串或 `null`。让它保持简单,避免同时从多个位置接受令牌。

    js
    import cookieParser from "cookie-parser";
    import { expressjwt } from "express-jwt";
    
    app.use(cookieParser());
    app.use(
      expressjwt({
        secret: getSigningKey,          // e.g. jwks-rsa's expressJwtSecret(...)
        algorithms: ["RS256"],
        getToken: (req) => req.cookies.access_token ?? null,
      }),
    );
  2. 2.

    豁免公开路由,或让身份验证变为可选

    `.unless()` 会跳过列出的路径。`credentialsRequired: false` 会放行不带令牌的请求,此时没有 `req.auth`,由各个路由自行决定如何处理。

    js
    app.use(
      expressjwt({ secret, algorithms: ["HS256"] }).unless({ path: ["/health", "/login", /^\/public\//] }),
    );
    
    // Or keep authentication optional and decide per route:
    app.use(expressjwt({ secret, algorithms: ["HS256"], credentialsRequired: false }));
  3. 3.

    把错误转换为规范的 401 响应

    Express 的默认错误处理函数会使用错误的 `status`(401),但响应的是一个 HTML 页面——在开发环境中还包含堆栈跟踪——而且没有 `WWW-Authenticate` 头。你需要自己把 `UnauthorizedError` 映射为带有该响应头的 JSON 401 响应。

    js
    app.use((err, req, res, next) => {
      if (err.name === "UnauthorizedError") {
        return res.status(401).set("WWW-Authenticate", "Bearer").json({ error: err.code });
      }
      next(err);
    });

相关错误

浏览完整的签名错误库