Search code examples
jwtpassport.jsjson-web-token

Passport JWT JSON Web Token authenticate error


I am implementing, for the first time, an authentication involving passport and JWT. My question is this: when I send an already expired token in the header, I get the message "Unauthorized". My code is as follows:

In routes.js:

app.route('/people/:id')
        // .all(function(req, res, next) {
        //     app.auth.authenticate(req, res, next);
        // })
        // .all(app.auth.authenticate)
        .all(app.auth.authenticate())
        .get(controller.getPeopleById)
        .delete(controller.deletePeople);

The commented parts are all that I have tried

In auth.js:

var passport = require("passport");
var passportJWT = require("passport-jwt");
var ExtractJwt = passportJWT.ExtractJwt;
var Strategy = passportJWT.Strategy;

module.exports = function(app) {
    const options = {
        secretOrKey: app.config.config.jwtSecret,
        jwtFromRequest: ExtractJwt.fromAuthHeader()
    };

    var strategy = new Strategy(options, function(payload, done) {
        console.log("payload: " + JSON.stringify(payload));
    });

    passport.use(strategy);

    return {
        initialize : function() {
            return passport.initialize();
        },

        authenticate : function() {
            return passport.authenticate('jwt', app.config.config.jwtSession);
            // return passport.authenticate('jwt', app.config.config.jwtSession, function(error, done, info) {                    
            //     if (error) {
            //         console.log("error: " + error);
            //     }

            //     if (done) {
            //         console.log("done: " + JSON.stringify(done));
            //     }

            //     if (info) {
            //         console.log("info: " + info);
            //     }
            // });
            // }
        }
    }
};

In middlewares.js:

var bodyParser = require("body-parser");
var config = require("./config/config")();

module.exports = function(app) {
    app.set("port", config.port || 3000);

    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    app.use(app.auth.initialize());
};

All I want to do is capture the error that happens in the authentication to customize the messages, for example: "Token expired, log in again" but as it is, it does not enter the validation method of the strategy. Has anyone ever experienced this? Grateful.


Solution

  • Passport always throws an AuthenticationError.

    To get the actually error, you have to provide a callback to the passport.authenticate method.

    Example:

    app.get('/protected', function(req, res, next) {
            passport.authenticate('local', function(err, user, failuresOrInfo, status) {
    
            // failuresOrInfo has the cause.
    
              if (err) { return next(err) }
             if (!user) { return res.redirect('/signin') }
             res.redirect('/account');
            })(req, res, next);
          });
    

    See the code snipted for passport code:

    function allFailed() {
          if (callback) {
            if (!multi) {
              return callback(null, false, failures[0].challenge, failures[0].status);
            } else {
              var challenges = failures.map(function(f) { return f.challenge; });
              var statuses = failures.map(function(f) { return f.status; });
              return callback(null, false, challenges, statuses);
            }
          }
    
    ...
    

    See that, if callback is present, passport passes the result to the callback and you have to manage the rest.

    Hope my answer is clear and it can help you.