使用 passport-jwt 验证节点 API

Authenticating node API with passport-jwt

我正在尝试使用 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. 向我的用户 /login 端点添加了一个令牌结果

    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);
    };
    

到这里为止一切都很好。我可以登录用户(使用护照本地身份验证)并且响应是我希望的...

{ "user": { "_id": "56c8b5bd80d16ef41ec705dd", "email": "peachy@keen.com", "password": "a$zd ... etc.", "__v": 0, }, "jwtToken": "JWT eyJ0eXAiOiJ .... etc." }

我创建了这样一条不受保护的测试路线...

// 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);
    

在我这样做之后,只有悲伤。我发送这样的请求:

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

永远,永远得到 401:

Unauthorized

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

拜托,关于我在上面犯的错误,或者至少如何进行调试,有什么想法吗??

对于跟随我的任何可怜的灵魂:passport-jwt 文档暗示授权 header 应该看起来像这样...

Authorization: JWT JSON_WEB_TOKEN_STRING.....

事实证明这是误导(无论如何对我来说)。

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

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

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

更简单的:

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

呸。是我吗,还是在这么多节点包文档中对这些事情的解释如此不充分真是令人失望?

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

Authorization: JWT JSON_WEB_TOKEN_STRING.....

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

Extracting the JWT from the request

There are a number of ways the JWT may be included in a request. In order to remain as flexible as possible the JWT is parsed from the request by a user-supplied callback passed in as the jwtFromRequest parameter. This callback, from now on referred to as an extractor, accepts a request object as an argument and returns the encoded JWT string or null. Included extractors

A number of extractor factory functions are provided in passport-jwt.ExtractJwt. These factory functions return a new extractor configured with the given parameters.

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.