I'm building a Sails.js app that includes a user login. As the documentation instructs, when a user signs in, the session records her id in the session accordingly:
req.session.userId = createdUser.id;
In most of the examples, each route performs a lookup on this ID, if it's present, and sends the authenticated user to the view if found. This strikes me as very inefficient. EVERY view needs to know if there's a signed-in user in order to display her name in the upper left corner. So, if I understand right, every view includes a trip to the database to look up the user, even if I reduce the amount of code by creating a policy that performs this lookup for every route.
What I would rather do is record the user's information in the session so that, once she is authenticated, that information is automatically present to every view:
req.session.userId = createdUser.id;
createdUser.loggedIn = true;
req.session.user = createdUser;
// the createdUser object does NOT contain the encrypted password or other sensitive info
This then allows me to just check in the template for a signed-in user like so from the layout
parent template (and any child template). (I'm using server-side views.)
{% if (session.user && session.user.loggedIn) %}
<li><a href="/profile/{{ session.user.id }}">Hi there, {{ session.user.username }}</a></li>
{% else %}
<li><a href="/signin">Sign In (if you want)</a></li>
{% endif %}
My question is whether this poses a security risk of any kind. It seems MUCH more efficient than looking up the User in every view, but perhaps there's a reason that documentation seems to advise this?
In most of the examples, each route performs a lookup on this ID, if
it's present, and sends the authenticated user to the view if found
FYI, ideally this should be handled by a policy.
This strikes me as very inefficient. EVERY view needs to know if
there's a signed-in user in order to display her name in the upper
left corner. So, if I understand right, every view includes a trip to
the database to look up the user, even if I reduce the amount of code
by creating a policy that performs this lookup for every route.
Either you make extra roundtrips to the database or you bloat your sessions. Both have their pros and cons. E.g. when creating a backend application that does not have to scale, I do not care about this extra database lookups. However when I have hundred thousands of users I should care. You have to consider this when you architect your application. Applications that need to scale like to use e.g. redis as a session store for optimization.
So to answer your question, yes it is okay to store username etc. in the session object to avoid extra database lookups. I am not a security expert, but I would not suggest to store any sensitive user information in the session like passwords.
BTW I highly recommend using http://passportjs.org/. It integrates with sails very well.
To get you started:
- http://iliketomatoes.com/implement-passport-js-authentication-with-sails-js-0-10-2/
- https://www.airpair.com/express/posts/expressjs-and-passportjs-sessions-deep-dive
In this example you can see how username, email and the roles of the user are stored in the session object:
passport.serializeUser(function(user, done) {
var sessionUser = { _id: user._id, name: user.name, email: user.email, roles: user.roles }
done(null, sessionUser);
});