Search code examples
node.jsjson-web-token

Login Example with nodejs and jsonwebtoken: can't read the token verification result


My MIDDLEWARE checks if the tokens provided by users are correct. The secuirity control, implemented by using jsonwebtoken, was inside the middleware and it was working fine. After I decided to move all this security checks in another file: TokenManger.js

But I don't know how to set the code between the two files. I tried many ways but no one is working.

So just for a better understanding I paste in the following an example code, which is not working. This is about the middleware:

...
router.use(function(req,res,next){
        var token = req.body.token || req.query.token || req.headers['x-access-token'];
        //decode token
        if(token){
            TokenManager.verifyToken(token,true,function(err,key){
                if(err) return res.json({ success : false, message : "Failed to authenticate token"});
                else next();
            });
        }else{
            // no token, return error
            return res.status(403).send({
                success : false,
                message: 'No token provided!'
            });
        }
});
...

In the other hand this is an example (and not working) implementation of the TokenManager.js:

var _ = require('lodash');
var jwt = require('jsonwebtoken');
var config = require('../../config.js');

var TokenManager = { 
    createToken: function(user) {
        if(user.admin){
            var token = jwt.sign(user, config.SECRET_WORD.ADMIN,{expiresIn:config.EXPIRE_TIME.ADMIN_TOKEN});
        }else{
            var token = jwt.sign(user, config.SECRET_WORD.USER,{expiresIn:config.EXPIRE_TIME.USER_TOKEN});  
        }
        return token;
    },
    verifyToken: function(token, admin, decode){
        if(admin){
            //admin authentication
            jwt.verify(token, config.SECRET_WORD.ADMIN, function(err,key){
                if(err){
                    return false;
                }else{
                    return true;
                }
            });
        }else{
            //user authentication
            jwt.verify(token, config.SECRET_WORD.USER, function(err,key){
                if(err){
                    return false;
                }else{
                    return true;
                }
            });
        }
    }
}

module["exports"] = TokenManager;

Actually the createToken(user) function is working fine with the previous code, there is a problems only with the verifyToken(token, admin, decode) function. But I care about the design so if you have suggestions about the creation too, they are more than welcome.

Just to complete the picture, this is how I call the createToken(user) function:

...
.post(function(req,res){
        User.findOne({ username: req.body.username }, function(err,user){
            if(err) throw err;
            if(!user){
                res.json({ success: false, message: 'Authentication failed. User not found!' });
            }else{
                if(user.password != req.body.password){
                    res.json({ success: false, message: 'Authentication failed. Wrong password!' });
                }else{
                    //token creation
                    var token = TokenManager.createToken(user);
                    res.json({
                        success: true,
                        token: token
                    });
                }
            }
        });
    });
...

Solution

  • You are passing function(err, key) to verifyToken, but there is not callback in the signature of verifyToken.

    Try changing the verifyToken function to

    verifyToken: function(token, admin, callback){
        if(admin){
            //admin authentication
            jwt.verify(token, config.SECRET_WORD.ADMIN, callback);
        }else{
            //user authentication
            jwt.verify(token, config.SECRET_WORD.USER, callback);
        }
    }
    

    Update : Without callback

    verifyToken: function(token, admin){
        try {
           if(admin){
              //admin authentication
              jwt.verify(token, config.SECRET_WORD.ADMIN, callback);
           }else{
              //user authentication
              jwt.verify(token, config.SECRET_WORD.USER, callback);
           }
           return true;
        } catch(err)
           return false;
        }   
    }
    

    And use like this in your middleware:

    if (TokenManager.verifyToken(token,true)){
        return next();
    } else {
        return res.json({ success : false, message : "Failed to authenticate token"});
    }