Search code examples
node.jsjwtpassport.jsjson-web-token

json web tokens, passport-jwt and its verify function


I've been doing some research on json web tokens recently. From what i've gathered, one of its great strengths is that its stateless. Everything you need to authenticate the user comes with the request, therefore you don't need to "hit the database on every request" as many articles state.

However, if i'm not mistaken, the docs for passport-jwt do just that, they hit the database on each request. That is, for each request that requires passport authentication.

passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    //this is a database call
    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 
        }
    });
}));

I was under the impression that by the time this function is called, the token has already been verified, otherwise this function would not be called and the user gets a 401 unauthorized.

So why check the database for the user? Since this code is in the docs, i'm doing the same thing by checking the database, but do i really need to? Why shouldn't i just do this

passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    //this is a database call
    done(null, {id: jwt_payload.sub})
}));

Solution

  • I dissagree with Leandro. He is incorrect when he says:

    Someone could use its own token, to access your API.`

    You are correct in your thinking, and it's the main driver for JWT autentication. You verify with password using another passport stratergy, and issue your signed JWT token. As it's signed by your sekret it cannot be modified. Any other JWT token created with another sekret would fail validation.

    I was just about to create an issue with passport-jwt and I found this closed issue, where someone pointed out the problem you have with the documentation.

    I haven't used passport-jwt as I found it easier just using passport-custom, and just setting the cookie myself.

    It is worth noting that you may still need to check the database. If you had an API call like api\getSuperSekretUserInfo\[userId] then you will need to check the request.user.id === params.userId (or whatever). Similarly, if you were accessing api\getInvoice\231 you will need to check the invoice with id 231 belongs to the user in the request.user.

    The JWT validation only checks that the token was issued by you, i.e. the user has logged on. But you can be sure that the information in the token has not been tampered with, and use that for any further checks - which may or may not require a database call.