Passport session not updating - node.js

I'm trying to update the passport session after user info change using:
user.save(function(err) {
if (err) return next(err)
// What's happening in passport's session? Check a specific field...
console.log("Before relogin: "+req.session.passport.user.changedField)
req.login(user, function(err) {
if (err) return next(err)
console.log("After relogin: "+req.session.passport.user.changedField)
res.send(200)
})
})
But even after re-login, with no errors my passport session remains the same. I have to manually logout and log back in for the session info to update. Can anyone explain what's happening?

Passport sets req.user using the function you have provided with passport.deserializeUser. You are using req.session.passport.user which is incorrect. There is no need to re-login after change of user information - deserializeUser is called on every request, and this is where you fetch the user information from your database. Then you access it via req.user.

Related

Refresh passport.js session data using req.login()

I'm using passport.js. The problem is when I change user information such as user name, It's not changed until user re-login. If user logout and login again, the information changed. but I want to change in the session without re-logging in.
My deserializeUser function like below, It looks different original passport's example because it is pickup data from session instead of querying database. I want to up loading speed so I didn't use database query on deserialize function.
passport.deserializeUser(function(userSession, done){
var member = { id : userSession[0], name : userSession[1] };
done(null, member);
});
So I think I have to use req.login() like below, but the session wouldn't changed.
Members.findOne({_id : someId }, function(err, member){
member[username] = req.body.username;
member.save(function (err){
if(err) return next();
console.log('The original session :'+req.sessionId);
req.login(req.user, {}, function(err){
if (err) return next();
console.log('The new session :'+req.sessionId);
res.send(200);
});
})
})
The problem is original session and new session is same, How can I force to refresh req.user object?
I red this document but didn't get solution.
https://github.com/jaredhanson/passport/issues/208

Passport deserialize function is removing user from the session

To be frank, I just started learning passport today. I feel I understand some of how passport is working, but I'm still trying to familiarize myself. My problem here (I think) is that my user is getting removed from the session, which is preventing me from reaching my authenticated routes. I console.logged the user id in the deserialize function to check if it was getting stored in the session, and it is ...
//serialize user into the session
passport.serializeUser(function(user,done){
done(null,user.id);
});
//deserialize the user from the session
passport.deserializeUser(function(id,done){
console.log('user id is: ' + id); //works and logs user id
User.findById(id, function(err,user){
done(err,user);
});
});
Here are my routes and passport middleware ...
app.post('/login', function(req,res,next){
passport.authenticate('local-login', function(err,user,info){
if(err){
console.log("we have an internal error!");
return next(err);
}
if(!user){
return res.send({success:false, message:'failed to login!'});
}else{
req.login(user, function(err){
if(err){
return next(err);
}
return res.send({ success : true, message : 'authentication succeeded' });
});
}
})(req,res,next);
});
//route middleware to make sure that a user is logged in
function isLoggedIn(req,res,next){
//if the user is authenticated in the session, carry on
if(req.isAuthenticated()){
next();
}
//if they are not authenticated in the session, redirect them to the home page
res.redirect('/');
}
Any help, insights, advice is greatly appreciated; thanks!
It's because you're always redirecting the user to the index page in your isLoggedIn middleware. Need to use return:
function isLoggedIn(req,res,next){
if(req.isAuthenticated()){
next();
// STOPS further execution of this function and prevents redirecting the user
return;
}
res.redirect('/');
}
Keep in mind that it's just JavaScript - no framework does any changes - Express, Passport, even Promises are pure JS and they don't modify the way the virtual machine works. GL!
p.s.
If things go wrong, especially in the beginning, I recommend using if-else statement. You wouldn't have problems this way:
if (req.isAuthenticated()) {
next();
} else {
res.redirect('/');
}

Passport update session isn't persisting

I'm trying to update my user session with a new name, an easy task I thought.
I'm a logged in user and in hitting a 'update' route and I've defined my own middleware to update the session:
module.exports = function(req, res, next) {
console.log(req.user);
req.login(req.body.user, function(err) {
if (err) return next(new Error('Error updating user profile'));
console.log('USER UPDATED *******', req.user);
next();
});
};
It took a bit of time to dig out the above code which should simply update the Passport session object. It correctly logs the previous session, and then the updated session but when I navigate to a new page after the inital response the user object is entirely lost and just returns {}.
Any ideas?
source
To log in a user and persist it into session passport uses a serialize function which typically stores user.id as a cookie and a deserialize function which retrieves that cookie and does a User.findById database call to find the associated user, and if found one, that's the user object that gets stored in req.user.
req.login passes whatever you pass it as the first argument directly to passport.serialize, which otherwise would've typically come from a strategy, which itself would've retrieved the user object from a database call, or created one.
So when you use req.login you need to pass it the user object that passport.serialize actually would've received, so that it could store the id in a cookie.
In your case, you were doing req.login(req.body.user, ... and since req.body.user comes from a POST Form variable it must not have the id that passport.serialize would've stored in the cookie.
You should instead use the new values from req.body.user and update req.user itself, and then do req.login(req.user, ...
var _ = require('lodash');
module.exports = function(req, res, next) {
//using lodash merge the updated user into the cached user
_.merge(req.user, req.body.user);
req.login(req.user, function(err) {
if (err) return next(new Error('Error updating user profile'));
console.log('USER UPDATED *******', req.user);
next();
});
};

How to log in with passport.js after resetting the password in Node.js?

I am working with passport.js for authentication.
I have an issue which I want to resolve:
Whenever user want to reset his password, I send an email of password reset link to him with token id.
And he can reset his password after clicking that link, but after resetting password,
I want the user being redirect to dashboard page instead of log in page.
I try to find out solution with passport.js but didn't get any luck.
Can someone give me any idea to resolve this issue?
Thank You
when the user resets the password you need to authenticate the user on user's behalf.
Code would look something like this
app.post('/resetpassword', function(req, res, next) {
/*
code to reset the password
*/
// append username and new password to req.body
// assuming passport still uses username and password as field indicator
req.body.username= "user_name";
req.body.password= "user_new_password";
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.sendStatus(401); }
// it is your responsibility to establish the session
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.rediect("to_users_dashboard_path");
});
})(req, res, next);
});
Note: while using custom callback, it is applications responsibility to establish the session, see Custom Callback

Update logged in user details in session

I am using PassportJS with ExpressJS.
I need to update the logged in user details. While I do update this in the DB, how do I update it in the session too so that request.user contains the updated user details?
That is, after updating the database, how do I update the session info on the user as well?
I tried directly assigning the updated details to request.user but it did not work.
I then tried request.session.passport.user - this worked but there is a delay of around 5 to 10 seconds before it gets updated in request.user too.
Is there a function that I need to call that updates the user information stored in the session? Or is there some other object that I can update where the change does not have a delay
I've been hunting down an answer for this too. Never mentioned in any docs or tutorials!
What seems to work is, after saving your newly updated user, do req.login(user)...
// "user" is the user with newly updated info
user.save(function(err) {
if (err) return next(err)
// What's happening in passport's session? Check a specific field...
console.log("Before relogin: "+req.session.passport.user.changedField)
req.login(user, function(err) {
if (err) return next(err)
console.log("After relogin: "+req.session.passport.user.changedField)
res.send(200)
})
})
The clue was here... https://github.com/jaredhanson/passport/issues/208
User.findById(req.user._id,function(err,doc){
req.logIn(doc,function(err1){
if(err1){ console.log("Error : "+err1) }
else{
res.render("abc.ejs",{user:req.user});
console.log('Item Removed Successfully!!!');
}
});
});
Here we are re-login the user
User => Mongoose Model
I had similar problem today and decided to share my findings, since i couldn't find similar answer.
The problem was that (copied from passport documentation) i was getting the user data directly from the token, that the user sent in the request. Which was of course outdated.
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey : CONFIG.JWT_SECRET
},
function (jwtPayload, cb) {
return cb(null, jwtPayload);
}
));
while i should get the fresh user object from the database instead:
return User.findById(jwtPayload.id)
.then(user => {
return cb(null, user);
})
.catch(err => {
return cb(err);
});

Resources