使用passport-jwt验证节点API

时间:2016-02-20 20:05:53

标签: javascript node.js passport.js

我尝试使用passport-jwt设置JWT身份验证。我认为我采取了正确的步骤,但测试GET不会成功,我也不知道如何调试它。

这就是我所做的:

  1. 尽可能设置passport-jwt straight out of the doc

    var jwtOptions = {
        secretOrKey: 'secret',
        issuer: "accounts.examplesoft.com",  // wasn't sure what this was, so i left as defaulted in the doc
        audience: "yoursite.net"   // wasn't sure what this was, so i left as defaulted in the doc
      };
    
    jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeader();
    
    passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
      User.findOne({id: jwt_payload.sub}, function(err, user) {
        if (err) {
            return done(err, false);
        }
        if (user) {
            done(null, user);
        } else {
            done(null, false);
            // or you could create a new account
        }
      });
    }));
    
  2. 向我的用户/登录端点添加了令牌结果

    var jwt = require('jsonwebtoken');
    // ...
    
    exports.postLogin = function(req, res, next) {
      passport.authenticate('local', function(err, user, info) {
        if (err) throw err;
        if (!user) {
            return res.send({ msg: 'Login incorrect' });
        }
        req.logIn(user, function(err) {
            if (err) throw err;
            var secretOrKey = jwtOptions.secretOrKey;
            var token = jwt.sign(user, secretOrKey, {
                expiresIn: 631139040 // 20 years in seconds
            });
            res.send({ user: user, jwtToken: "JWT " + token });
        });
      })(req, res, next);
    };
    
  3. 事情看起来很顺利。我可以登录用户(使用本地身份验证),响应是我希望的......

      

    {       "用户":{           " _id":" 56c8b5bd80d16ef41ec705dd",           "电子邮件":" peachy@keen.com",           "密码":" $ 2a $ 10 $ zd ...等。",           " __ v":0,       },       " jwtToken":" JWT eyJ0eXAiOiJ ....等。" }

    我创建了一个不受保护的测试路线......

    // in my routes file
    app.get('/user/tokenTest', user.tokenTest);
    

    在我的控制器中,一个简单的终点......

    exports.tokenTest = function(req, res) {
        console.log(req.headers);
        res.send("token test!!");
    };
    

    GET-ing也很好。

    1. 但是我试着像这样保护那条路线:

      app.get('/user/tokenTest', passport.authenticate('jwt', { session: false }),
          user.tokenTest);
      
    2. 在我这样做之后,只有悲伤。我发送了这样的请求:

      curl -k 'https://localhost:3443/user/tokenTest' -H 'Authorization: JWT eyJ0eXAiOiJ... etc.' 
      

      总是,总是得到401:

        

      未经授权

      控制器中的控制台日志似乎没有执行,也没有登录passport.use策略方法。我已经进行了调整和调整,但我有点失落。护照-jwt文档仅提供示例,几乎没有其他帮助。

      请问,关于我上面的错误,或者至少如何进行调试的任何想法?

2 个答案:

答案 0 :(得分:26)

对于跟随我的任何可怜的灵魂:passport-jwt doc意味着auth标题看起来应该像这样......

  

授权:JWT JSON_WEB_TOKEN_STRING .....

结果证明这是误导性的(无论如何)。

幸运的是,感谢this article我能够了解令牌的构建方式。 (令牌的前缀直到第一个'。'是该方案的base64编码。前面的JWT"噪声阻止验证工作

所以解决方法是更改​​用户控制器返回的令牌:

    res.send({ user: user, jwtToken: "JWT " + token });

更简单:

    res.send({ user: user, jwtToken: token });

呼。是这样的,或者在如此多的节点包文档中解释这些东西是不是真的很糟糕?

答案 1 :(得分:0)

我可能会迟到但我有类似的问题,我有另一个解决方案。您可以使用此options.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('JWT')从身份验证标头中提取JWT令牌,格式如下:

  

授权:JWT JSON_WEB_TOKEN_STRING .....

以下是我使用的文档:https://github.com/themikenicholson/passport-jwt

  

从请求中提取JWT

     

JWT可以通过多种方式包含在请求中。在   为了保持尽可能灵活,JWT从中解析   用户提供的回调请求作为jwtFromRequest传入   参数。这个回调,从现在开始称为提取器,   接受请求对象作为参数并返回编码的JWT   字符串或null。包含的提取器

     

提供了许多提取器工厂功能   护照jwt.ExtractJwt。这些工厂功能返回一个新的   使用给定参数配置的提取器。

fromHeader(header_name) creates a new extractor that looks for the JWT in the given http header
fromBodyField(field_name) creates a new extractor that looks for the JWT in the given body field. You must have a body parser configured in order to use this method.
fromUrlQueryParameter(param_name) creates a new extractor that looks for the JWT in the given URL query parameter.
fromAuthHeaderWithScheme(auth_scheme) creates a new extractor that looks for the JWT in the authorization header, expecting the scheme to match auth_scheme.
fromAuthHeaderAsBearerToken() creates a new extractor that looks for the JWT in the authorization header with the scheme 'bearer'
fromExtractors([array of extractor functions]) creates a new extractor using an array of extractors provided. Each extractor is attempted in order until one returns a token.