【问题标题】:Nodejs Restify - Valide Jwt id_token with jwksNodejs Restify - 使用 jwks 验证 Jwt id_token
【发布时间】:2021-06-14 17:19:55
【问题描述】:

我们开发一个应用程序,前面是 VuejS,后面是一个 api Nodejs(Restify)。 我们使用第三方为我们提供身份验证(具有 OpenId Connect 协议的身份提供者)。

因此,使用 VueJs 我们可以进行身份​​验证,获取 access_tokenid_token,然后将其传递到每个带有承载的 nodejs 请求标头中。

现在我们需要在后面验证此令牌是否有效以及用户是否可以访问此路由。

我们的身份提供者为我们提供了一个端点 (jwks_uri),其键如下:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "AXDJKLFJDLKFJLKJFLKSJDFLKJSFL",
      "e": "AQAB",
      "n": "2T3QDw6gcSDFS........................VRtQSDQSDQSDQSD"
    }
  ]
}

我从中提取了公钥,结果类似于:

-----BEGIN PUBLIC KEY-----
MIIB......................OCAQ8AMIIBCgKCAQEA2T3QDw6gcqrTZRy74XWy
Bn0JoQzg/H2QX.............................................fqX13O
4QIDAQAB
-----END PUBLIC KEY-----

现在我想用这个公钥验证 id_token 我尝试这样的事情

jwt.verify(token, publicKey, { algorithms: ['RS256'] }, function(err, decoded) {
    //This will display the decoded JWT token.
    console.log(decoded)  
});
  1. 但我不知道如何正确使用验证来检查有效性? 索赔?

  2. 我是否必须每次对我想要的每条道路重做相同的处理 保护?像这样?

server.get('/data1', async function (req, res, next) {
    try {
        helper.validAccessToken(req).then(function(res) => {
            if(res){
                data=getData();
                res.send(data) ;
            } else{
                res.send(401, {message: 'Unauthorizd'}) 
            }
        });
    } catch (err) {

        return next(err);
    }
});

【问题讨论】:

    标签: node.js api authentication jwt openid-connect


    【解决方案1】:

    我相信中小型应用程序的最佳方式就是让 jwt 验证作为中间件工作。比如:

    // authUser.js
    
    module.exports = function authUser(req, res, next) {
        const token = getJwtToken(req)
        jwt.verify(token, publicKey, { algorithms: ['RS256'] }, function(err, decoded) {
            if (err) {
              res.send(401, 'Unauthorized')
              return next(false)
            }
            return next()
        })
    }
    
    

    并将其包含到您要限制访问的路由的中间件链中。

    server.get("/secure", authUser, function (req, res, next) {
      res.send(200, "secure route response");
      return next();
    });
    
    server.get("/", function (req, res, next) {
      res.send(200, "public route response");
      return next();
    });
    

    codesandbox link

    对于大型应用程序,我相信您需要更灵活和可配置的东西。能够引入不同的安全级别和身份验证策略。以及更灵活的路线配置。

    【讨论】:

      【解决方案2】:

      感谢您的解决方案。 但是我使用restify和restify,似乎不可能为每个路由指定一个中间件?但显然,当我们这样做时,它适用于整个完整的应用程序:

      serve.use(authUser)
      

      有没有办法正确地做到这一点?还是我维护一系列需要保护的路由,如果我在其中一条路由上,我会签入 req?

      【讨论】:

        【解决方案3】:

        最后我受到了你的建议的启发。

        我实现了一个检查令牌并添加 req 属性的函数。这个函数我用作“中间件”

         async function authUser(req, res, next) {
          try{    
            req.isLogged=false
            console.log(req.params);
            let isvalid = await validAccessToken(req);
            console.log(">>> isValid : " + isvalid);
            if(isvalid===true){
              //token verifié on passe en preview false
              req.isLogged=true
              return next()
            }else{
              console.log("Unauthorized");
              req.isLogged=false
              return next()                
            }
          }catch(error){
        
            res.send(401, 'Unauthorized ' + error)
            return next()
          }
        }
        

        我把这个函数像中间件一样放在了restify server中:

        server.use(openid.authUser);
        

        在此之后,在我想要保护的每条路线中,我都会检查此属性:

        const preview = ! req.isLogged ;
        

        【讨论】:

          猜你喜欢
          • 2020-09-03
          • 2020-03-27
          • 2017-03-30
          • 2017-03-31
          • 2020-02-24
          • 1970-01-01
          • 2016-01-17
          • 2023-04-06
          • 2017-08-25
          相关资源
          最近更新 更多