'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