I am building a SPA using express, mongoose and passportjs.
I have created a simple schema for my user:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
first_name: String
}, { collection: 'users' });
User.plugin(passportLocalMongoose);
mongoose.model('User', User);
Configured passport using the User
object which mongoose gave me:
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
And configured my app to authenticate the user when navigating to this route:
app.post('/login', passport.authenticate('local'), function(req, res, next) {
if (req.isAuthenticated()) {
return res.json({ state: 'success', user: { first_name: req.user.first_name } });
}
return res.json({ state: 'failure', message: 'cannot authenticate' });
});
Now I am able to successfully authenticate a user. And the browser saves a session id cookie.
My problem is that every time the user refreshes the page passport won't deserialize the user using the session id, what makes the user unauthenticated.
While accessing the req.user
object in the site's root I get undefined
what make me realize passport doesn't deserialize the user properly:
app.use('/', function (req, res, next) {
console.log(req.user); // prints undefined.
next();
});
What is the proper way for restoring a user after refreshing the page?
I am building a SPA using express, mongoose and passportjs.
I have created a simple schema for my user:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
first_name: String
}, { collection: 'users' });
User.plugin(passportLocalMongoose);
mongoose.model('User', User);
Configured passport using the User
object which mongoose gave me:
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
And configured my app to authenticate the user when navigating to this route:
app.post('/login', passport.authenticate('local'), function(req, res, next) {
if (req.isAuthenticated()) {
return res.json({ state: 'success', user: { first_name: req.user.first_name } });
}
return res.json({ state: 'failure', message: 'cannot authenticate' });
});
Now I am able to successfully authenticate a user. And the browser saves a session id cookie.
My problem is that every time the user refreshes the page passport won't deserialize the user using the session id, what makes the user unauthenticated.
While accessing the req.user
object in the site's root I get undefined
what make me realize passport doesn't deserialize the user properly:
app.use('/', function (req, res, next) {
console.log(req.user); // prints undefined.
next();
});
What is the proper way for restoring a user after refreshing the page?
Share Improve this question edited Apr 18, 2015 at 18:58 Matan Givoni asked Apr 18, 2015 at 18:31 Matan GivoniMatan Givoni 1,1261 gold badge14 silver badges37 bronze badges 1-
Mongoose must be deserializing the user, if you're calling
passport.deserializeUser(User.deserializeUser());
– Plato Commented Apr 18, 2015 at 19:29
2 Answers
Reset to default 5The solution is to store the sessions in the DB. I used connect-mongo.
app.js:
var mongoose = require('mongoose');
var expressSession = require('express-session');
var MongoStore = require('connect-mongo')(expressSession);
mongoose.connect(db_url, function (err) {
if (err) {
console.log(err);
}
});
app.use(expressSession({
secret: process.env.SESSION_SECRET || 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
after this, req.isAuthenticated()
returns true
on every request even after refreshing the page. (Thanks to app.use(passport.session())
which es before any route handler)
app.use('/', function (req, res, next) {
if (req.isAuthenticated()) {
// returns true if a user already logged in.
}
next();
});
Looking at your post i can guess where problem is happening. In question you have pasted your back end expressjs code, but the problem is happening in the front end.
Think of a situation when you are working on normal javascript files, you make some edit in the variable values using Chrome dev tools of firebug n all. Let's say you refresh the page, do you still see the same edited value in the view? No right. Same is the case with your view, you are temporary holding user data. Although your backend is holding the values in req.user but your front end loses it when you refresh.
So you have to do either of below two :
- Store your value in cookie on successful login and erase it when logged out. So that cookie is never going to loose data even if you refresh the page. Access the user data from that cookie whenever you need it
- Call the backend API which returns value of req.user on your every page refresh
I am not sure what frontend framework you are using for SPA, if you are using AngularJS then you can make use of cookieStore service it does the job beautifully.