如何在安全的 httponly cookie 中验证发送到客户端的 JWT?

How do I validate JWT sent to client in secure, httponly cookie?

提问人:Greg Lafrance 提问时间:8/30/2023 更新时间:9/1/2023 访问量:65

问:

在我的 NodeJS 应用程序 RESTful API 中,当用户登录时,我创建一个 JWT 并将其发送到安全的 httponly cookie 中的客户端:

const jwt = utils.createJWT(user._id.toString());
const sessionId = utils.generateSessionId();

res.cookie(sessionId, jwt, { httpOnly: true, secure: true });

return res.status(200).json({ 
  userId: user._id,
  result: constants.SUCCESS
});

登录后,后续 API 调用浏览器会自动将安全 cookie 发送到服务器。

我需要验证 JWT 是否未过期,如果它已过期,则需要刷新 JWT。

但是在对服务器的请求中,cookie似乎是加密的,那么如何提取JWT来检查它是否已过期呢?

最终,我试图做的是确保我可以验证 JWT 以查看它是否已过期,但我读到您不应该存储 JWT 服务器端,这是真的吗,我是否应该尝试从安全 cookie 中提取 JWT,如果是这样,如何?

节点 .js 安全 cookie JWT httponly

评论


答:

0赞 sherryyy 8/31/2023 #1

如果您没有通过 expires 选项为 jwt 设置到期日期,那么您的 jwt 将永远不会过期。我建议将过期时间存储在 a 中,以提高安全性。(更多信息见:如何在nodejs中将jwt令牌到期时间设置为最大?如果你想设置一个,你可以这样做:.env

(这里我使用有效载荷数据进行编码)user._id

const signToken = id => {
  return jwt.sign({ id }, process.env.JWT_SECRET_STRING, {
    expiresIn: process.env.JWT_expires_in
  });
};
const createSendToken = (user, statusCode, res) => {
  const token = signToken(user._id);
  const cookieOptions = {
    expires: new Date(
      Date.now() + process.env.JWT_COOKIE_EXPIRES_IN
    ),
    httpOnly: true
  };
  if (process.env.NODE_ENV === 'production') {
 // cookie will only sent on an encrypted connection
    cookieOptions.secure = true;
  }
  res.cookie('jwt', token, cookieOptions);

接下来,至于检查您的令牌是否已过期: 您可以通过 jwt 的验证功能轻松验证您的令牌,并检查它是否已过期。我将使用基于承诺的方法:

const { promisify } = require('util');
// 1) verify token

const decoded = await promisify(jwt.verify)(
  req.cookies.jwt,
  process.env.JWT_SECRET_STRING
);

如果你,你会发现到期时间。您可以根据需要处理错误。这些将是 a 和 a .
另请注意,具有异步和同步版本。(在这里阅读更多:jwt.verify() 的 Node.js 回调)
console.log(decoded)JsonWebTokenErrorTokenExpiredErrorjwt.verify)

但是,请记住,JWT 是一个非常适合 RESTful API 的 stateles 解决方案。无需在服务器上存储会话状态。此外,如果用户的 jwt 已过期,请让他们重新登录,以便向他们发出新的 jwt。您可以查看他们的文档以获取更多信息: https://www.npmjs.com/package/jsonwebtoken

评论

0赞 Greg Lafrance 9/1/2023
我确实在 JWT 上设置了过期时间,但我不知道如何使用该过期时间。我还想有一个刷新令牌,但无论如何,对我来说,第一步是验证 JWT 过期是否有效。那么如何编码呢?JWT 嵌入在安全的 httponly cookie 中,因此当用户发出后续请求时,并且 cookie 会自动附加到请求中,如何提取 JWT 并验证它是否未过期?还是我应该做一些完全不同的事情?
0赞 sherryyy 9/1/2023
您可以设置一个 5 秒的短过期时间,使用 jwt.verify func 并将其放入 try/catch 中。过期后,它会给出我上面写的错误。抱歉,我不熟悉使用刷新和访问令牌方法,所以我无法帮助您。您可以阅读其他一些 SO 帖子,例如:(stackoverflow.com/questions/27726066/jwt-refresh-token-flow)或者希望知识渊博的人可以帮助您。