使用JWT访问令牌和刷新令牌方法保护REST API

使用JWT访问令牌和刷新令牌方法保护REST API,rest,authentication,jwt,passport.js,mern,Rest,Authentication,Jwt,Passport.js,Mern,我正在使用MERN堆栈构建一个web应用程序。我已经制作了一个RESTAPI,以通常的方式与前端交互,但我无法找到构建安全API和应用程序整体安全性的最佳方法 到目前为止,这就是我所尝试的 验证用户/请求的流程: 1.用户输入凭据 2.服务器使用access\u-token和refresh\u-token响应,在redis缓存中缓存refresh\u-token,将电子邮件作为密钥,并在本地存储中缓存access\u-token 3.要访问受保护的路由,用户使用请求头中的承载{access\u

我正在使用MERN堆栈构建一个web应用程序。我已经制作了一个RESTAPI,以通常的方式与前端交互,但我无法找到构建安全API和应用程序整体安全性的最佳方法

到目前为止,这就是我所尝试的

验证用户/请求的流程:
1.用户输入凭据
2.服务器使用
access\u-token
refresh\u-token
响应,在redis缓存中缓存
refresh\u-token
,将电子邮件作为密钥,并在本地存储中缓存
access\u-token

3.要访问受保护的路由,用户使用请求头中的
承载{access\u TOKEN}
发送请求
4.服务器检查令牌是否有效且未过期,为用户返回受保护的资源
5.如果
access\u令牌
过期(我将令牌过期时间缩短,例如5分钟),则从前端启动一个操作(使用redux操作),一个示例请求:

POST http://localhost:3000/user/token
Header Bearer {ACCESS_TOKEN}
Body 
  {
     "email" : "user@example.com"
  }
  • 如果电子邮件具有
    refresh\u令牌,服务器将在redis缓存中执行检查
  • 如果是,服务器用更新的
    access\u令牌响应
  • 这就是我在代币上签名的方式

    const signToken = user => {
    
        let email = user.email;
        let name = user.name;
    
        const accessToken = JWT.sign({
                                iss : process.env.APP_NAME,
                                sub : user.id,
                                email : email,
                                name : name
                            }, JWT_SECRET, {
                                expiresIn : 300
                            });
    
        const refreshToken = JWT.sign({
                                    iss : process.env.APP_NAME,
                                    sub : user.id,
                                    email : email,
                                    name : name
                                }, REFRESH_TOKEN_SECRET, {
                                    expiresIn : '30d'
                                });
    
        // Save to redis cache
        REDIS_CLIENT.set(email, refreshToken);
    
        return {accessToken, refreshToken};
    }
    
    以及获取新的
    访问\u令牌

    // Refresh token
    const refreshToken = (req, res, next) => {
    
        const extractToken = req.headers['authorization'];
        const token = extractToken.split(' ')[1];
    
        if (!token) {
            return res.status(403).json({
                message : 'Unauthorized'
            });
        }
    
        REDIS_CLIENT.get(req.body.email, (err, cachedToken) => {
            if (err) return res.status(500).json({message : 'Something went wrong'});
    
            if (cachedToken == null) {
                return res.status(403).json({message : 'Unauthroized'});
            } else {
    
                JWT.verify(cachedToken, REFRESH_TOKEN_SECRET, (err, rt) => {
                    if (err) {
                        return res.status(500).json({message : 'Something went wrong'})
                    } else {
                        // Generate a new access token here
                        const newAccessToken = JWT.sign({
                                    iss : process.env.APP_NAME,
                                    sub : rt.sub,
                                    email : rt.email,
                                    name : rt.name
                                }, JWT_SECRET, {
                                    expiresIn : 300
                                });
    
                        return res.json({
                            "accessToken" : newAccessToken
                        });
                    }
    
                });
    
            }
        });
    }
    
    这种方法安全吗?如果不是,如果堆栈是MERN,那么设计身份验证流的一些好方法是什么。在搜索互联网时,许多人建议在
    access\u token
    中设置短到期,并使用
    refresh\u token
    生成新的
    access\u token
    ,但我还没有找到如何在用户处于非活动状态时注销用户的方法?如果攻击者获得过期的令牌和电子邮件id,并生成新的访问令牌怎么办?oAuth集成将如何实现


    PS:很抱歉在这里放了这么多东西,在互联网上搜索了很多次后才来到这里,但什么也没找到

    你用这个/找到了什么好的资源吗?你用这个/找到了什么好的资源吗?