I have a server in node.js using express and passport with the passport-local
strategy.
I have the users in the database and through passport I'm able to authenticate them, unfortunately when a second request comes from the same client the req.isAuthenticated()
method returns false
.
There is also no user in the request (req.user = undefined
).
I've also checked and when doing the authentication although I get back a user from passport.authenticate('local'...
I do not get req.user
populated then. If I try to set it up manually it just doesn't propagate for following requests.
I don't understand what I'm doing wrong, here is my code.
server.js
var express = require('express'),
compass = require('node-compass'),
routes = require('./server/routes')
http = require('http'),
path = require('path'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
Database = require('./server/repositories/database'),
Configuration = require('./server/config').Config,
crypto = require('crypto');
var app = express();
app.enable("jsonp callback");
passport.use(new LocalStrategy(
function(email, password, done) {
process.nextTick(function () {
var userService = new UserService();
userService.login(email, crypto.createHash('md5').update(password).digest("hex"), function(error, user) {
if (error) done(error, user);
else if (!user) return done(null, false, { message: 'wrong credentials'});
return done(null, user);
});
});
}
));
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
var userService = new UserService();
userService.findById(id, function(err, user) {
done(err, user);
});
});
app.configure(function(){
app.set('port', Configuration.Port);
app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(compass({
project: path.join(__dirname, 'app'),
sass: 'styles'
}));
app.use(express.session({ secret: 'keyboard cat' }));
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'app')));
});
routes.configure(app);
Database.open(function() {
app.listen(Configuration.Port, function() {
console.log("Express server listening on port " + Configuration.Port);
});
});
routes.js
var Configuration = require('./config').Config;
var ApiResult = require('../model/apiResult').ApiResult;
var ApiErrorResult = require('../model/apiErrorResult').ApiErrorResult;
var ApiReturnCodes = require('../model/apiReturnCodes').ApiReturnCodes;
var passport = require('passport');
var usersController = require('./controllers/usersController');
exports.configure = function(app) {
function ensureAuthenticated(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) { return next(); }
else {res.send(new ApiErrorResult(ApiReturnCodes.NOT_LOGGED_IN, null));}
}
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) { console.log(info); res.send(new ApiErrorResult(ApiReturnCodes.ENTITY_NOT_FOUND, null)); }
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user
else res.send(new ApiResult(user));
})(req,res,next);
});
app.get('/anotherLink', ensureAuthenticated, function(req, res, next) {
res.json({Code:0});
});
}
When I hit the link /anotherLink
after being authenticated I get res.isAuthenticated()
as false.
Also when I see the req.session
after the ensureAuthenticated
is called I get:
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {} }
What am I missing for it to save the information that that user is authenticated? On the client side I'm using Angular only doing a simple get with the url without parameters.
If I forgot to put something here just tell me, I'll update it. Any help will be greatly appreciated. Thanks
Passport is a popular, modular authentication middleware for Node. js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.
This function is primarily used when users sign up, during which req. login() can be invoked to automatically log in the newly registered user.
Authorization is performed by calling passport. authorize() . If authorization is granted, the result provided by the strategy's verify callback will be assigned to req.account . The existing login session and req.
So I found out what was wrong with my code.
My passport.deserializeUser
method used the method userService.findById
And that called the repository... like this:
userRepository.findUnique({"_id": id}, callback);
because the id
was generated by MongoDB
the correct call needs to be:
userRepository.findUnique({"_id": new ObjectID(id)}, callback);
I hope this saves some time to the next person with the same problem.
With this detail, this code should work nicely for everyone wanting to use the LocalStrategy
on the Passport
framework.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With