如何认证&使用使用Passport.js的Remote NodeJS API授权客户端Web应用程序

时间:2017-08-08 06:33:42

标签: javascript node.js api express passport.js

如下图所示,我有一个独立的API项目在服务器上运行,端口为3001,我在服务器上运行了一个端口为3002的Web App。

Flow of Web APP to API

端口 3001上的API ,具有Web App(及移动应用)获取和放置数据所需的所有API路由,包括Authentication API(使用{ {1}}和passport-local)。在项目的API方面,我还处理了用户角色授权,每个路由都有可以访问API的角色列表。

示例路线

passport-jwt

端口3001中的角色授权API方法

todoRoutes.get('/', 
               requireAuth,
               AuthController.roleAuth(['user','editor','admin']),
               TodoController.getTodos);

登录成功后的响应json就像这样

exports.roleAuth = function(roles){

    return function(req, res, next){

        var user = req.user;

        User.findById(user._id, function(err, foundUser){

            if(err){
                res.status(422).json({error: 'No user found.'});
                return next(err);
            }

            if(roles.indexOf(foundUser.role) > -1){
                return next();
            }

            res.status(401).json({error: 'You are not authorized to view this content'});
            return next('Unauthorized');

        });
    }
}

现在在 Web App 中,我想使用相同的角色授权和身份验证(登录),但是你看,Web App没有连接到数据库,让我查询一下是否用户检查用户在会话中有效,并且具有在登录成功后获得的响应中的角色。

摘要 以下是我在这个问题中寻找的要点:

  1. 通过端口3001上的远程API登录客户端Web应用程序(已实现)
  2. 获取用户令牌和其他信息(上面显示的响应)(已实现)
  3. 确保用户在客户端Web App上进行身份验证,并记住用户登录的角色,以便使用这些信息来授权客户端应用程序上的每个路由。在客户端应用程序中,我有几个页面,其中包含用于将数据发送到端口 3002 上的服务器端API的表单,这些页面由两个不同的用户使用,其中包含 editor 和< EM>管理员
  4. TIA

4 个答案:

答案 0 :(得分:1)

您的身份验证API应返回嵌入了保证信息(角色)的JWT。此外,令牌应使用您的视图API已知的秘密进行。

例如,使用npm模块jsonwebtoken,请按以下方式签名:

<a class='new_message' tabindex='-1' href='#dataTextBox'> New Message</a>

然后,在您的视图API上,使用passport-jwt,它会验证令牌并为您提供与您签名的原始对象匹配的有效内容。使用有效负载作为用户对象:

token = jwt.sign( {
    exp: Math.floor( Date.now() / 1000 ) + ( 60 * 60 ), // 1 hour
    i: user._id,
    role: user.role
}, "my-secret" );

在此阶段,您的用户至少经过身份验证。如果要将视图限制为某些角色,可以添加第二个中间件:

passport.use( new JwtStrategy( {
    secretOrKey: "my-secret"

}, ( payload, callback ) => callback( null, payload ) ) );

const authenticate = () =>
    passport.authenticate( "jwt", { session: false, failWithError: true } )

如果您的视图需要有关用户的更多信息,则身份验证API将需要在JWT(因此保证)或外部(不保证,但会产生较小的令牌)中提供该信息。

答案 1 :(得分:0)

exports.roleAuth = function(roles){

return function(req, res, next){

    var user = req.user;

    User.findById(user._id, function(err, foundUser){

        if(err){
            res.render('index.html');
        }

        if(roles.indexOf(foundUser.role) > -1){
            res.render('another.html');
        }

        res.render('another2.html');

    });
}

}

答案 2 :(得分:0)

我认为有两种方法可以做到,但并不完美。

一种是使用特定视图的主api端点。通常,每个视图都有一个主端点,如果该端点返回Unauthorized / Forbidden状态,则不应渲染视图。但是这个解决方案存在问题,并不总是有一个匹配视图的主要端点。

其他选项是命名具有角色的路由,例如admin/dashboardusers/dashboard,并且用户应该有一个描述其角色的字段,例如。 user.role。在渲染视图之前,请检查url和API返回的用户对象中的相应角色。

第二个选项是首选,这是我通常使用的。

希望它有所帮助。

答案 3 :(得分:0)

JWT的优点是不是已经解决了这个问题,或者更确切地说可以通过正确的实现解决您的问题?

所需要的只是

  1. 初始化 WebApp 中的passport-jwt模块,方法与在 API 中初始化模块的方式相同,即secretOrKey参数。
  2. 检查JWT,特别是role属性,并根据
  3. 允许/拒绝