JWT身份验证中刷新令牌的正确实现是什么

时间:2020-07-30 14:02:21

标签: node.js express jwt

我正在尝试使用jsonwebtoken在我的React&Nodejs应用程序中实现JWT身份验证。

我目前有一个JWT身份验证,当唱歌时会生成一个access_token。我想在应用程序中正确实现JWT,因此我也希望实现refresh_token的使用。

我的问题:实现此目标的最佳方法是什么?如何阻止潜在的攻击者访问用户的refresh_token来访问受保护的资源?

代码:

创建令牌的用户登录路线:

router.post("/login", async (req, res) => {
  const { username, password, remember } = req.body;

  if (!username || !password) {
    return res.status(400).json({ message: "Please fill in all fields." });
  }

  try {
    // find user based on username
    const user = await User.findOne({ username });
    if (isEmpty(user))
      return res.status(400).json({ message: "User does not exists." });

    // compare requested password to db password with bcrypt
    const isValid = await bcrypt.compare(password, user.password);

    if (!isValid)
      return res.status(400).json({ message: "Invalid credentials" });

    // sign a JWT token to user
    const token = jwt.sign({ id: user.id }, config.get("jwtSecret"), { expiresIn: 3600, });

    // if remember user === true sign a refresh token to the user
    if(remember) {
      const refreshToken = jwt.sign({ id: user.id }, config.get("jwtSecret"), { expiresIn: '30d'});
    }
    // send user & tokens to frontend

  } catch (error) {
    console.log(error);
  }
  

需要成功才能访问用户数据的中间件:

function auth(req, res, next) {
  const token = req.header("x-auth-token");

  if (!token)
    return res.status(401).json({ message: "No token, authorization denied." });

  try {
    const decoded = jwt.verify(token, config.get("jwtSecret"));
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(400).json({ message: "Token is not valid" });
  }
}

在路由器中使用此中间件访问用户数据:

// GET api/auth/user
// DESC get user data based on token

router.get("/user", auth, (req, res) => {
  User.findById(req.user.id)
    .select("-password")
    .then((user) => {
      return res.status(200).json({
        user: {
          id: user.id,
          username: user.username,
          email: user.email,
        },
      });
    });
});

我的refresh_token到哪里来完成我的安全JWT身份验证?

1 个答案:

答案 0 :(得分:0)

您的刷新令牌只有一个作业:生成访问令牌,就是这样,不直接访问资源,这是访问令牌作业。

这样做,您可以在生成的访问令牌上设置较短的到期日期,因为一旦到期,您将给用户一个请求另一个的机会。我真的看不到将它们存储在数据库中的意义。

1-关于一堆代码,请使用另一个密钥对刷新令牌进行签名,不要对两个令牌使用相同的密钥。

2-确保为每个用户存储刷新令牌,以便能够在需要时将其撤消,并检查他是否真正拥有它们(数据库检查)。

3-创建一条为用户生成新的access_token的路由(例如/ token)(在这里,您需要检查数据库中该用户确实拥有他正在使用的刷新令牌)。