'passport-jwt in MEAN-Stack returning Internal Server Error 500
Im using passport.js JWT strategy to authenticate my MEAN-Stack app. The unsecured routes work properly but i cant get the secured routes to work. they allways return Internal Server Error 500 even though im sticking to the docs. Here is the code:
im initializing in index.js before applying routes:
server.use(passport.initialize());
My passport.js setup file:
const JwtStrategy = require('passport-jwt').Strategy,
      ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../models/user');
const config = require('../config/db');
module.exports = function(passport) {
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
  User.findOne({_id: jwt_payload._id}, function(err, user) {
      if (err) {
          return done(err, false);
      }
      if (user) {
         return done(null, user);
      } else {
         return done(null, false);
      }
  });
}));
};
My Route that doesnt work:
const express = require('express');
const router = express.Router();
const config = require('../config/db');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
require('../config/passport');
const passport = require('passport');
router.get('/profile', passport.authenticate('jwt', {session: false}), function(req, 
 res){
     res.json(user);
 });
module.exports = router;
my token is setup properly since i can decode it manually.
How im calling this route from angular (i know that i actually dont need the userId parameter for the call itself):
public getProfile(userId) : any{
let httpOptions = {
  headers: new HttpHeaders({ 'Authorization': `Bearer ${this.token}` })
};
this.http.get('http://localhost:8080/api/v1/profile', httpOptions).subscribe(res => {
  console.log('got the profile for user with id: ' + userId + '=> ' + res);
  return res;
}, err => {
  console.log(err);
});
}
Any help is appreciated. Thanks in advance for your time!
EDIT: Mongoose logs
Mongoose: users.findOne({ _id: ObjectId("5bcf1218cace7d1168a23672") }, { 
projection: {} })
GET /api/v1/profile 500 4.579 ms - 5
OPTIONS /api/v1/profile 204 0.097 ms - 0
{ _id: '5bcf1218cace7d1168a23672',
 email: '[email protected]',
 password: '$2a$10$z8li41jQMESsmbIyQUsPfO6VkYjOyO/ybj4lW04VGUkJmlShydBN.',
 name: '12',
 age: 12,
 gender: 'male',
 description: '12',
 question: '12',
 __v: 0,
 iat: 1540419498 }
 Mongoose: users.findOne({ _id: ObjectId("5bcf1218cace7d1168a23672") }, { 
 projection: {} })
 GET /api/v1/profile 500 3.995 ms - 5
Solution 1:[1]
I have added single-line comments to hit spots, verify the spots and comment accordingly to further debug. Confirm /api/v1/ is an express root route.
passport.js
const JwtStrategy = require('passport-jwt').Strategy,
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../models/user');
const config = require('../config/db');
module.exports = function(passport) {
  let opts = {
    secretOrKey: config.secret,
    jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    issuer: 'TODO', // configure issuer
    audience: 'TODO' // configure audience
  };
  passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    console.log(jwt_payload); // confirm _id is defined
    User.findOne({ _id: jwt_payload._id }, function(err, user) {
      if (err) {
          return done(err, false);
      }
      if (!user) {
         return done(null, false);
      }
      return done(null, user);
    });
  }));
};
route.js
const express = require('express');
const passport = require('passport');
const jwt = require('jsonwebtoken');
const config = require('../config/db');
const User = require('../models/user');
const router = express.Router();
require('../config/passport');
router.get('/profile', passport.authenticate('jwt', { session: false }), function(req, res) {
     res.json(req.user); // use req.user not user
});
module.exports = router;
Solution 2:[2]
Had the same issue. Seems like the way you are returning the done(null, user) callback needs to be modified. Try this.
User.findOne({ _id: jwt_payload._id }, function(err, user) {
  if (err) {
      return done(err, false);
  }
  if (!user) {
     return done(null, false);
  }
  // Your code should process further if you get user. Returning 
  // here will terminate your program early. Hence, protected 
  // route is not accessed.
  done(null, user); 
 });
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Akinjide | 
| Solution 2 | Sumit Gautam | 
