I need a "Remember Me" checkbox when logging in like this . And I add a middleware before using passport
app.use(function (req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = 1000 * 60 * 3;
} else {
req.session.cookie.expires = false;
}
}
next();
});
app.use(passport.initialize());
app.use(passport.session());
I can not login when req.body.rememberme is true and the user is remembered when req.body.rememberme is false.
I also tried connect-ensure-login and it still wrong.
and another question: when should I delete the cookies in my database and how?
:)
Other code is exactly the same as the passport guide
route:
app.get('/', passport.authenticate('local', {failureRedirect: '/login'}), function (req, res) { res.redirect('/user/home'); });
app.post('/login', passport.authenticate('local', {failureRedirect: '/login'}), function (req, res) { res.redirect('/user/home'); });
sessions:
passport.serializeUser(function(user, done) {
var CreateAccessToken = function() {
var token = user.GenerateSalt();
User.findOne({accessToken: token}, function(err, existingUser) {
if (err) return done(err);
if (existingUser) {
CreateAccessToken();
} else {
user.set('accessToken', token);
user.save(function(err) {
if (err) return done(err);
return done(null, user.get('accessToken'));
})
}
});
};
if (user._id)
CreateAccessToken();
});
passport.deserializeUser(function(token, done) {
User.findOne({accessToken: token}, function(err, user) {
if (err) return done(err);
return done(err, user);
});
});
and the strategie:
passport.use(new LocalStrategy(function(userId, password, done) {
User.findOne().or([{username: userId}, {email: userId}]).exec(function(err, user) {
if (err) return done(err);
if (!user) {
return done(null, false, {message: 'Invalid password or username'});
}
if (user.Authenticate(password)) {
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password or username'});
}
});
}));
I noticed that Express will update the cookie only when hash value changed. so I have modified the code in the middleware
app.use(function (req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = 1000 * 60 * 3;
req.session._garbage = Date();
req.session.touch();
} else {
req.session.cookie.expires = false;
}
}
next();
});
now I can login with "Remember Me", but it only works on chromium and firefox on Ubuntu. I still can not login with the "Remember Me" checkbox on chrome and firefox on Win7 and Android.
I checked response header when POST to "/login" on chrome on win7 and it had the same "Set-Cookie" field as it on Ubuntu, why it can not work?
Time is out of sync...so I post a extra time field.
$('#login').ajaxForm({beforeSubmit: function(arr, $form, option) {
arr.push({name: '__time', value: (new Date()).toGMTString()});
}});
and the "RememberMe" middleware:
app.use(function (req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = moment(req.body.__time).add('m', 3) - moment();
req.session._garbage = Date();
req.session.touch();
} else {
req.session.cookie.expires = false;
}
}
next();
});
I had exactly the same problem as you. The following code works for me:
app.post("/login", passport.authenticate('local',
{ failureRedirect: '/login',
failureFlash: true }), function(req, res) {
if (req.body.remember) {
req.session.cookie.maxAge = 1000 * 60 * 3;
} else {
req.session.cookie.expires = false;
}
res.redirect('/');
});
There is now a Passport strategy for adding Remember Me functionality writen by Jared Hanson.
https://github.com/jaredhanson/passport-remember-me
This works by issuing a unique remember-me token during every session that is consumed at the start of the next (invalidating it for future use.) As a result, this is likely to be a more secure solution.
Ensure that app.use(express.bodyParser()) is placed above your middleware, as you are relying on req.body.rememberme