I've got Passport setup to authenticate users stored in mongodb. Seems to work fine: authentication succeeds/fails appropriately and session variables get set. However, getting Passport to check for a session is failing. Something seems to be quite wrong in that the console.log statements I've added to the deserializeUser callback never see the light of day. I assume my problem is related to deserializeUser never being called. Anyone able to diagnose my misstep?
// Passport configuration
passport.serializeUser(function(user, cb){ cb(null, user.id) });
passport.deserializeUser(function(uid, cb){
console.log("Trying to deserialize user: "+uid);
User.findById(uid, function(err, user){
cb(err, user);
});
});
// auth strategy function
passport.use(new LocalStrategy({usernameField: 'email'},
function(email, pass, done){
User.findOne({email: email}, function (err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, {message: "Couldn't find user"});
var crypted = bcrypt.hashSync(pass, user.salt);
if(user.hashpass != crypted)
return done(null, false, {message: "Bad password"});
return done(null, user);
});
}
));
passport.CreateSession = function (req, res, next) {
passport.authenticate('local', function(err, user, info){
if(err || !user)
return res.json({status: "Failure: "+err});
req.logIn(user, function (err){
if(err)
return res.json({status: "Failure: "+err});
return res.json({status: "Authenticated"});
});
})(req, res, next);
};
with the following in app.js:
app.post('/session', passport.CreateSession); // restify better
app.del('/session', passport.DestroySession);
app.get('/images', passport.CheckSession, routes.images);
Have you use()
'd passport.session()
middleware? Like in this example:
https://github.com/jaredhanson/passport-local/blob/master/examples/login/app.js#L88
That's what restores the session and calls deserializeUser
, so it sounds like that may be missing.
For anyone else who is having this issue, take a look at this:
app.use(session({
secret: 'something',
cookie: {
secure: true
}}));
If you have cookie.secure
set to true and you're NOT using SSL (i.e. https protocol) then the cookie with the session id is not returned to the browser and everything fails silently. Removing this flag resolved the problem for me - it took hours to realise this!
passport.serializeUser(
function(user, done){
done(null, user.id);
});
passport.deserializeUser(
function(id, done){
User.findById(id, function(err, user){
if(err){
done(err);
}
done(null, user);
});
});
**> try this one**
I fought the same problem the entire day. I had a custom callback set up to do authorizations (like at the bottom of http://passportjs.org/guide/authenticate/). It looks like Passport preprocesses all request objects before they even hit the other middleware (based on some logging statements I wrote). As part of that preprocessing, it places the deserialized user information into the request.user object. Unfortunately, the default behavior of passport.authenticate ('local', callback) seems to be to ignore any session or cookie data, and instead assume that the username and PW are being sent in the request object. What I did to fix this was to first check the request.user object, and if it existed, it meant that Passport had done its preprocessing and then I could call login directly. Here is my authorization function, which I use in place of passport.authenticate('local'):
function doAuth(request, response, next)
{
if (request.user) {
request.logIn(request.user, function (err) {
if (err) {
console.log(err);
response.status(500).json({message:
"Login failed. Auth worked. Nonsense"});
return;
}
console.log("doAuth: Everything worked.");
next();
});
return;
}
passport.authenticate('local', function(err, user, info) {
if (err) {
response.status(500).json({message: "Boo Passport!"});
return; //go no further
//until I figure out what errors can get thrown
}
console.log("Authentication failed. Here is my error:");
console.log(err);
console.log("Here is my info:");
console.log(info);
response.status(500).json({message: "Authentication failed."});
return;
}
request.logIn(user, function(err) {
if (err) {
console.log("Login failed. This is the error message:");
console.log(err);
response.status(500).json({message:"Login failed."});
return;
}
console.log("doAuth: Everything worked. I don't believe it.");
next();
});
})(request, response, next);
}