JWT身份验证中刷新令牌的正确实现是啥
Posted
技术标签:
【中文标题】JWT身份验证中刷新令牌的正确实现是啥【英文标题】:What is the proper implementation of a refresh token in JWT authenticationJWT身份验证中刷新令牌的正确实现是什么 【发布时间】:2020-11-20 07:09:49 【问题描述】:我正在尝试使用 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】:您的刷新令牌有 1 个工作:生成访问令牌,仅此而已,不直接访问资源,这是访问令牌工作。
通过这样做,您可以在生成的访问令牌上设置一个较短的过期日期,因为一旦过期,您将让用户有机会请求另一个访问令牌。我真的不明白将它们存储在数据库中的意义。
1- 关于你的一堆代码,使用另一个密钥来签署你的刷新令牌,不要为两者使用相同的密钥。
2- 确保为每个用户存储刷新令牌,以便能够在需要时撤销它们,并检查他是否真正拥有它们(数据库检查)。
3- 创建一个路由(例如 /token),为用户生成新的 access_tokens(这里你需要检查用户真正拥有他正在使用的刷新令牌的数据库)。
【讨论】:
以上是关于JWT身份验证中刷新令牌的正确实现是啥的主要内容,如果未能解决你的问题,请参考以下文章
Laravel JWT 令牌在身份验证 JWT 方法中刷新后无效