passport-jwt 401 Unauthorized

14,233

Solution 1

SHORT
Legacy
'JWT ' + [some token]

Version 0.4.0
'bearer ' + [some token]

EXAMPLE
So when you send the tokens now is like this:
Legacy
res.json ({ success: true, token: 'JWT ' + token })

Version 0.4.0
res.json ({ success: true, token: 'bearer ' + token })

In depth
There may be other ways to do this as well
If you look in the /node_module/passport-jwt/lib/extract_jwt.js file you can see that theres a function called versionOneCompatibility(options)

Solution 2

After many hours of trying finally I've managed to fix the problem by using the ExtractJwt.fromAuthHeaderWithScheme('Bearer') method. For some reason the extractor wasn't able to get the token with the other methods.

Solution 3

I've got the same issue and after researching i figured out what causing this problem. When you creating you res.json inside the route

//Authenticate
router.post('/authenticate', (req, res, next) => {
  const username = req.body.username;
  const password = req.body.password;

  User.getUserByUsername(username, (err, user) => {
    if (err) throw err;
    if (!user) {
      return res.json({
        success: false,
        msg: 'User not found'
      });
    }

    User.comparePassword(password, user.password, (err, isMatch) => {
      if (err) throw err;
      if (isMatch) {
        const token = jwt.sign(user.toJSON(), config.secret, {
          expiresIn: 604800 // 1 week
        });
        res.json({
          success: true,
          token: 'jwt ' + token, //Here you have to put space after name inside quotes
          user: {
            id: user._id,
            name: user.name,
            username: user.username,
            email: user.email
          }
        });
      } else {
        return res.json({
          success: false,
          msg: 'Wrong password'
        });
      }
    });
  });
});

inside the token:'jwt ' + token,it's really important to put a space behind the name jwt,and also the name you put inside ' ' quotation mark that name you have to put inside your

var opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');//Here you have to put the same name inside quotes '' like you put inside token but without space after name
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    console.log(jwt_payload);
    User.findOne({
        id: jwt_payload.sub
    }, function(err, user) {
        if (err) {
            return done(err, false);
        }

        if (user) {
            return done(null, user);
        } else {
            return done(null, false);
        }
    });
}));

These two have to match,it doesn't matter if you put jwt or JWT or bearer or anything else,the important thing is that they have to match,and there has to be space when you are creating token:'name '.

Share:
14,233
Borislav Popnikolov
Author by

Borislav Popnikolov

Updated on June 19, 2022

Comments

  • Borislav Popnikolov
    Borislav Popnikolov over 1 year

    I'm trying to implement passport-jwt authentication but I'm always getting 401 Unauthorized when trying to call the endpoint.

    Here is my setup

    passport.js

    var passport = require('passport');
    var User = require('../models/user');
    var config = require('./auth');
    var JwtStrategy = require('passport-jwt').Strategy;
    var ExtractJwt = require('passport-jwt').ExtractJwt;
    var LocalStrategy = require('passport-local').Strategy;
    
    var localOptions = {
        usernameField: 'email'
    };
    
    var localLogin = new LocalStrategy(localOptions, function(email, password, done) {
    
        User.findOne({
            email: email
        }, function(err, user) {
            if (err) {
                return done(err);
            }
            if (!user) {
                return done(null, false, { error: 'Login failed. Please try again' });
            }
    
            user.comparePassword(password, function(err, isMatch) {
                if (err) {
                    return done(err);
                }
                if (!isMatch) {
                    return done(null, false, { error: 'Login Failed. Please try again.' });
                }
    
                user.status = 'online';
                user.save(function(err, user) {
                    if (err) {
                        return done(err);
                    }
                });
    
                return done(null, user);
            });
        });
    });
    
    var jwtOptions = {
        jwtFromRequest: ExtractJwt.fromHeader('Authorization'),
        secretOrKey: config.secret
    };
    
    var jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
        console.log(payload);
        User.findById(payload._id, function(err, user) {
            if (err) {
                return done(err, false);
            }
            if (user) {
                done(null, user)
            } else {
                done(null, false);
            }
        });
    });
    
    passport.use(localLogin);
    passport.use(jwtLogin);
    
    module.exports = {
        initialize: () => passport.initialize(),
        authenticateJWT: passport.authenticate('jwt', { session: false }),
        authenticateCredentials: passport.authenticate('local', { session: false }),
    };
    

    user.js

    var express = require('express');
    var router = express.Router();
    var AuthController = require('../controllers/authentication');
    var passportService = require('../config/passport');
    var passport = require('passport');
    
    const requireToken = passportService.authenticateJWT;
    const requireCredentials = passportService.authenticateCredentials;
    
    
    router.post('/signup', AuthController.register);
    router.post('/signin', requireCredentials, AuthController.login);
    
    router.get('/protected', requireToken function(req, res, next){
    res.send({msg:'Success!'});
    });
    
    module.exports = router;
    

    I've made sure that my header contains: 'JWT ' + [some token]... Also tried without the 'JWT ' still nothing...

    I've checked the other posts about the same problem but still can't resolve it.

  • Bhagvat Lande
    Bhagvat Lande about 5 years
    i have used the same but it will also not solving problem i am using V4.0.0 ,can you please elaborate how to add this token in response or please create demo if possible