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.
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
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
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 '.
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 calledversionOneCompatibility(options)
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.