express-jwt

This module provides Express middleware for validating JWTs (JSON Web Tokens) through the jsonwebtoken module. The decoded JWT payload is available on the request object.该模块提供Express中间件,用于通过jsonwebtoken模块验证JWT(JSON Web Tokens)。已解码的JWT负载在请求对象上可用。

Install安装

$ npm install express-jwt

API

expressjwt(options)

Options has the following parameters:选项具有以下参数:

The available functions have the following interface:可用功能具有以下界面:

Usage用法

Basic usage using an HS256 secret:使用HS256密码的基本用法:

var { expressjwt: jwt } = require("express-jwt");
// or ES6
// import { expressjwt, ExpressJwtRequest } from "express-jwt";

app.get(
  "/protected",
  jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

The decoded JWT payload is available on the request via the auth property.已解码的JWT有效载荷可通过auth属性在请求上获得。

The default behavior of the module is to extract the JWT from the Authorization header as an OAuth2 Bearer token.模块的默认行为是从Authorization标头中提取JWT作为OAuth2承载令牌

Required Parameters所需参数

The algorithms parameter is required to prevent potential downgrade attacks when providing third party libraries as secrets.当提供第三方库作为机密时,需要algorithms参数来防止潜在的降级攻击。

⚠️ Do not mix symmetric and asymmetric (ie HS256/RS256) algorithms不要混合对称和非对称(即HS256/RS256)算法: Mixing algorithms without further validation can potentially result in downgrade vulnerabilities.:在没有进一步验证的情况下混合算法可能会导致降级漏洞。

jwt({
  secret: "shhhhhhared-secret",
  algorithms: ["HS256"],
  //algorithms: ['RS256']
});

Additional Options其他选项

You can specify audience and/or issuer as well, which is highly recommended for security purposes:您还可以指定访问群体和/或颁发者,出于安全目的,强烈建议您这样做:

jwt({
  secret: "shhhhhhared-secret",
  audience: "http://myapi/protected",
  issuer: "http://issuer",
  algorithms: ["HS256"],
});

If the JWT has an expiration (exp), it will be checked.如果JWT有过期(exp),则将对其进行检查。

If you are using a base64 URL-encoded secret, pass a Buffer with base64 encoding as the secret instead of a string:如果您使用的是base64 URL编码的机密,请传递一个带有base64编码的Buffer作为机密,而不是字符串:

jwt({
  secret: Buffer.from("shhhhhhared-secret", "base64"),
  algorithms: ["RS256"],
});

To only protect specific paths (e.g. beginning with /api), use express router call use, like so:要仅保护特定路径(例如以/api开头),请使用express router调用use,如下所示:

app.use("/api", jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }));

Or, the other way around, if you want to make some paths unprotected, call unless like so.或者,反过来说,如果您想使某些路径不受保护,请用如下方式调用unless

app.use(
  jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
  }).unless({ path: ["/token"] })
);

This is especially useful when applying to multiple routes. 这在应用于多条管线时尤其有用。In the example above, path can be a string, a regexp, or an array of any of those.在上面的示例中,path可以是字符串、正则表达式或其中任何一个的数组。

For more details on the .unless syntax including additional options, please see express-unless.有关.unless语法(包括其他选项)的更多详细信息,请参阅express-unless

This module also support tokens signed with public/private key pairs. 该模块还支持使用公钥/私钥对签名的令牌。Instead of a secret, you can specify a Buffer with the public key您可以使用公钥指定缓冲区,而不是密钥

var publicKey = fs.readFileSync("/path/to/public.pub");
jwt({ secret: publicKey, algorithms: ["RS256"] });

Customizing Token Location自定义令牌位置

A custom function for extracting the token from a request can be specified with the getToken option. 可以使用getToken选项指定用于从请求中提取令牌的自定义函数。This is useful if you need to pass the token through a query parameter or a cookie. 如果您需要通过查询参数或cookie传递令牌,这很有用。You can throw an error in this function and it will be handled by express-jwt.您可以在这个函数中抛出一个错误,它将由express-jwt处理。

app.use(
  jwt({
    secret: "hello world !",
    algorithms: ["HS256"],
    credentialsRequired: false,
    getToken: function fromHeaderOrQuerystring(req) {
      if (
        req.headers.authorization &&
        req.headers.authorization.split(" ")[0] === "Bearer"
      ) {
        return req.headers.authorization.split(" ")[1];
      } else if (req.query && req.query.token) {
        return req.query.token;
      }
      return null;
    },
  })
);

Retrieve key dynamically动态检索密钥

If you need to obtain the key dynamically from other sources, you can pass a function in the secret parameter with the following parameters:如果需要从其他源动态获取密钥,可以使用以下参数传递secret参数中的函数:

For example, if the secret varies based on the issuer:例如,如果机密因发行者而异:

var jwt = require("express-jwt");
var data = require("./data");
var utilities = require("./utilities");

var getSecret = async function (req, token) {
  const issuer = token.payload.iss;
  const tenant = await data.getTenantByIdentifier(issuer);
  if (!tenant) {
    throw new Error("missing_secret");
  }
  return utilities.decrypt(tenant.secret);
};

app.get(
  "/protected",
  jwt({ secret: getSecret, algorithms: ["HS256"] }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Secret rotation秘密轮换

The getSecret callback could also be used in cases where the same issuer might issue tokens with different keys at certain point:getSecret回调也可用于同一发行者在某一点可能发行具有不同密钥的令牌的情况:

var getSecret = async function (req, token) {
  const { iss } = token.payload;
  const { kid } = token.header;
  // get the verification key by a given key-id and issuer.
  return verificationKey;
};

Revoked tokens已吊销的令牌

It is possible that some tokens will need to be revoked so they cannot be used any longer. 有些令牌可能需要被撤销,因此无法再使用。You can provide a function as the isRevoked option. 您可以提供一个函数作为isRevoked选项。The signature of the function is function(req, payload, done):函数的签名是function(req, payload, done)

For example, if the (iss, jti) claim pair is used to identify a JWT:例如,如果(iss, jti)声明对用于标识JWT:

const jwt = require("express-jwt");
const data = require("./data");

const isRevokedCallback = async (req, token) => {
  const issuer = token.payload.iss;
  const tokenId = token.payload.jti;
  const token = await data.getRevokedToken(issuer, tokenId);
  return token !== "undefined";
};

app.get(
  "/protected",
  jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
    isRevoked: isRevokedCallback,
  }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Handling expired tokens处理过期令牌

You can handle expired tokens as follows:您可以按如下方式处理过期令牌:

jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
    onExpired: async (req, err) => {
      if (new Date() - err.inner.expiredAt < 5000) { return;}
      throw err;
    },,
  })

Error handling错误处理

The default behavior is to throw an error when the token is invalid, so you can add your custom logic to manage unauthorized access as follows:默认行为是在令牌无效时抛出错误,因此您可以添加自定义逻辑来管理未经授权的访问,如下所示:

app.use(function (err, req, res, next) {
  if (err.name === "UnauthorizedError") {
    res.status(401).send("invalid token...");
  } else {
    next(err);
  }
});

You might want to use this module to identify registered users while still providing access to unregistered users. 您可能希望使用此模块来识别已注册用户,同时仍向未注册用户提供访问权限。You can do this by using the option credentialsRequired:您可以使用选项credentialsRequired

app.use(
  jwt({
    secret: "hello world !",
    algorithms: ["HS256"],
    credentialsRequired: false,
  })
);

Typescript

A Request type is provided from express-jwt, which extends express.Request with the auth property. express-jwt提供了Request类型,它使用auth属性扩展express.RequestIt could be aliased, like how JWTRequest is below.它可以是别名,就像下面的JWTRequest一样。

import { expressjwt, Request as JWTRequest } from "express-jwt";

app.get(
  "/protected",
  expressjwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
  function (req: JWTRequest, res: express.Response) {
    if (!req.auth?.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Migration from v6

  1. The middleware function is now available as a named import rather than a default one: import { expressjwt } from 'express-jwt'中间件函数现在可以作为命名导入而不是默认导入:import { expressjwt } from 'express-jwt'
  2. The decoded JWT payload is now available as req.auth rather than req.user解码的JWT有效载荷现在可以作为req.auth而不是req.user使用
  3. The secret function had (req, header, payload, cb), now it can return a promise and receives (req, token). secret函数有(req, header, payload, cb),现在它可以返回promise并接收(req, token)token has header and payload.token具有headerpayload
  4. The isRevoked function had (req, payload, cb), now it can return a promise and receives (req, token). isRevoked函数具有(req, payload, cb),现在它可以返回promise并接收(req, token)token has header and payload.token具有headerpayload

Related Modules相关模块

Tests

$ npm install
$ npm test

Contributors贡献者

Check them out here这里查看

Issue Reporting问题报告

If you have found a bug or if you have a feature request, please report them at this repository issues section. 如果您发现了错误或有功能请求,请在此存储库问题部分报告。Please do not report security vulnerabilities on the public GitHub issue tracker. 请不要在公共GitHub问题跟踪器上报告安全漏洞。The Responsible Disclosure Program details the procedure for disclosing security issues.责任披露计划详细说明了披露安全问题的程序。

Author

Auth0

License许可证

This project is licensed under the MIT license. See the LICENSE file for more info.