I'm having an absolute nightmare trying to set up JWT with my express app! Think I've got it mostly working now, I have a register route and login route that both work correctly and generate valid tokens and I have another route in my '/users' route that I test the authentication with and this is all fine. But I have another file containing routes for '/api' which is where the authentication is actually important and I have a similar test route that tries to access req.user (just like I do in my other route) but it seems like req.user is undefined. Through some debugging it looks like the user is in req.account which is very odd and I don't understand why its not in req.user
I define my jwt strategy in /config/passport.js
'use strict';
const User = require('../models/user'),
config = require('./main'),
JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
//exported to be used by passport in server set up
module.exports = function (passport) {
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling Passport where to find the secret
secretOrKey: config.secret
};
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
User.findById(payload._id, function(err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
});
passport.use(jwtLogin);
}
passport is passed as an argument to this and then initialised in the main express file
here is the /users route file, this works fine. sending a GET request to /users/isAuth with Authorization header and 'JWT ' works fine and I get my username sent back to me
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
User = require('../models/user'),
config = require('../config/main'),
passport = require ('passport');
function generateToken(user) {
return jwt.sign({_id: user._id}, config.secret, {
expiresIn: 10080
});
}
.
. Here are routes for login and register they perform as expected
. and work fine
.
/* ==================================
Test Authentication Route
================================== */
router.get('/isAuth', passport.authenticate('jwt', { session: false }), function(req, res) {
console.log(req.user);
res.json({username: req.user.username});
});
module.exports = router;
In this file though, for the api routes sending a request to GET /api/testAuth exactly the same as before with the same token and the same headers I get back no req.user and in the console I see that req.user is undefined. But in the console there does seem to be the user object just as req.account? I don't understand what is happening here hopefully someone can help!
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
Server = require('../models/server'),
passport = require('passport');
// Test route to see if logged in user is matt
router.get('/testAuth', passport.authorize('jwt', { session: false }), function(req, res) {
console.log(req.user);
if (req.user) {
if(req.user.username == "matt") {
res.send("You are matt!");
} else {
res.send("You are not matt!");
}
} else {
res.send("no req.user");
}
})
module.exports = router;
I'm having an absolute nightmare trying to set up JWT with my express app! Think I've got it mostly working now, I have a register route and login route that both work correctly and generate valid tokens and I have another route in my '/users' route that I test the authentication with and this is all fine. But I have another file containing routes for '/api' which is where the authentication is actually important and I have a similar test route that tries to access req.user (just like I do in my other route) but it seems like req.user is undefined. Through some debugging it looks like the user is in req.account which is very odd and I don't understand why its not in req.user
I define my jwt strategy in /config/passport.js
'use strict';
const User = require('../models/user'),
config = require('./main'),
JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
//exported to be used by passport in server set up
module.exports = function (passport) {
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling Passport where to find the secret
secretOrKey: config.secret
};
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
User.findById(payload._id, function(err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
});
passport.use(jwtLogin);
}
passport is passed as an argument to this and then initialised in the main express file
here is the /users route file, this works fine. sending a GET request to /users/isAuth with Authorization header and 'JWT ' works fine and I get my username sent back to me
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
User = require('../models/user'),
config = require('../config/main'),
passport = require ('passport');
function generateToken(user) {
return jwt.sign({_id: user._id}, config.secret, {
expiresIn: 10080
});
}
.
. Here are routes for login and register they perform as expected
. and work fine
.
/* ==================================
Test Authentication Route
================================== */
router.get('/isAuth', passport.authenticate('jwt', { session: false }), function(req, res) {
console.log(req.user);
res.json({username: req.user.username});
});
module.exports = router;
In this file though, for the api routes sending a request to GET /api/testAuth exactly the same as before with the same token and the same headers I get back no req.user and in the console I see that req.user is undefined. But in the console there does seem to be the user object just as req.account? I don't understand what is happening here hopefully someone can help!
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
Server = require('../models/server'),
passport = require('passport');
// Test route to see if logged in user is matt
router.get('/testAuth', passport.authorize('jwt', { session: false }), function(req, res) {
console.log(req.user);
if (req.user) {
if(req.user.username == "matt") {
res.send("You are matt!");
} else {
res.send("You are not matt!");
}
} else {
res.send("no req.user");
}
})
module.exports = router;
Share
Improve this question
asked Nov 13, 2016 at 1:09
imattacusimattacus
3541 gold badge3 silver badges12 bronze badges
1
- 1 Samson Maosa's answer solve my problem. – Jeex Commented Sep 22, 2019 at 14:56
2 Answers
Reset to default 18req.user
object is only set when you use a passport authentication strategy that uses sessions. In this case, the authentication is stateless since you have specified {session: false}
, which is how it should be for an api. Thus, the session does not have a user object. Here is how I set my req.user
object in the passport.authenticate
middleware:
Modify your
jwtOptions
to enable passing the req object toJwtStrategy
function:const jwtOptions = { // Telling Passport to check authorization headers for JWT jwtFromRequest: ExtractJwt.fromAuthHeader(), // Telling Passport where to find the secret secretOrKey: config.secret, passReqToCallback: true, //<= Important, so that the verify function can accept the req param ie verify(req,payload,done) };
Modify the parameters to your JwtStrategy to include the request object as the first parameter; then within the
if (user)
block, just assign the returned user object toreq.user
:const jwtLogin = new JwtStrategy(jwtOptions, function(req, payload, done) { User.findById(payload._id, function(err, user) { if (err) { return done(err, false); } if (user) { req.user = user; // <= Add this line done(null, user); } else { done(null, false); } }); });
That is it: now any route that has the passport.authenticate("jwt", {session: false})
middleware will receive req.user
upon successful authentication.
You are using passport.authorize
in your testAuth route, this is for users that are already logged in and have session information. Since you are not using session storage you do not have a persistent req.user
object and so should use passport.authenticate
on all routes
http://passportjs.org/docs/authorize