erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
11.99k stars 2.5k forks source link

Can sensitive information be saved in req.session.user cookie? #1075

Open leopoldjoy opened 8 years ago

leopoldjoy commented 8 years ago

Hello,

Can information be securely stored in req.session.user for example in the login script? For example would it be acceptable to store a user's name, email, password, userid, etc.? Or could this information ever be maliciously accessed? How can I authenticate if they're really logged in? Could they ever manually set this information? Do I need to setup a tokening system?

Trying to understand this simplified API example.

Thanks!

krukid commented 8 years ago

If you're asking whether your session contents can be read by the client, then no - not in your case. Basically you have to look at what session store you're using, if it's an internal database/file or server memory, then session contents are not accessible to the client, unless you intentionally expose them. If you're using a cookie-based session store, then watch out, because it means that your session with all of its content is passed to the client in a cookie, which is typically signed with a secret key that prevents modification, but more often than not is just base64-encoded rather than encrypted.

This does not mean, however, that a server-side session is 100% secure. If the client discovers someone's session ID (that is usually passed via cookie or a query string), then he can hijack that user's session, unless additional countermeasures are in place.

leopoldjoy commented 8 years ago

@krukid Thank you for the response! I mean in the current setup on react-redux-universal-hot-example example API, for example here. This is a server-side session, right? So it's safe except for hijacking? Where can I learn more about how to avoid hijacking?

krukid commented 8 years ago

To understand what happens with the session in RRUHE, the key lines you want to look at are:

https://github.com/erikras/react-redux-universal-hot-example/blob/master/package.json#L27 where we see that we actually start up two separate servers for the app and the API (no shared memory)

https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/server.js#L25 where the proxy is set up to forward requests from the app server to API server

https://github.com/erikras/react-redux-universal-hot-example/blob/master/api/api.js#L2 https://github.com/erikras/react-redux-universal-hot-example/blob/master/api/api.js#L19-L24 where we require the session management package for express.js and configure the session middleware

and finally read the docs of the package to see what that configuration means: https://github.com/expressjs/session

Putting all of the above together, you'll see that we're setting up a memory-based session store in our API server that is attached to the client via a cookie-based session ID. Initial request received from the client (browser) is handled by the app server that proxies any /api requests to that backend API server (that should only be accessible by the app server to avoid any direct attacks), along with the session ID cookie that allows it to get or set in-memory session data for the client. So, without any other means to access that memory except your own application logic, the client will not be able to read the session's contents and it's safe to write any secret values to it.

That said, you should avoid propagating sensitive data across different parts of your system to reduce the number of attack vectors. Consider using tokens and IDs instead of actual passwords, credit card numbers, etc wherever possible.

I'm sorry to say that I can't really recommend any specific sources for learning about Web security, since most of what I know I learned from practice, stackoverflow.com and, more generally, google.

As for session hijacking countermeasures: use HTTPS, make sure your session IDs aren't easily forged, track invalid session IDs and ban requests from IPs that use them, be creative and use common sense :)

leopoldjoy commented 8 years ago

@krukid Thanks so much for your detailed response, very helpful. What packages would you recommend for creating tokens that can be saved in the in-memory session data when the user logs-in (instead of passwords, as you suggested)? Thanks again!

krukid commented 8 years ago

@leopoldjoy I'm reluctant to encourage bad design here, but since I'm not familiar with your project and for the sake of example rather than anything else, you could just store a hash of your password inside the session, which is enough to keep the actual passwords isolated (see https://crackstation.net/hashing-security.htm). More generally, to generate temporary access tokens you can also use hashing (just make sure you know and understand your hash collision probabilities), built-in node crypto utils (https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) or use something more heavy-handed, like https://www.npmjs.com/package/uuid

leopoldjoy commented 8 years ago

@krukid Thanks for your responses. I have a few remaining questions:

1) Is it recommended to overwrite the default genid function here. In the express-session documentation it states that:

The default value is a function which uses the uid-safe library to generate IDs.

Can I leave this? Or should I try to create a unique hash (avoiding collisions) from the unique data stored in req.session?

2) Assuming cookie-hijacking does not occur and that all sessions are correctly destroyed upon logout, is this an acceptable way to determine if the user is currently logged in:

if (typeof req.session.user === 'object' && typeof req.session.user._id !== 'undefined') {
  // Protected area inside an API...
}

Is it fair to say that this is sufficient and that I don't need to re-verify the user's credentials (with a token system) since they were already verified when the internal data was set at login.

3) What measures can I take to try to prevent cookie hijacking? Apart from SSL, is saving the user's IP to the internal session the only approach? (This is not desirable since the user's IP can, of course, change and I would prefer the user to stay logged in.)

Thanks again for your help. This is really helping me understand this setup and express.