What's the difference between saveUninitialized and resave? - node.js

The session middleware for Express provides several configurable options.
resave: 'Forces the session to be saved back to the session store, even if the session was never modified during the request.'
saveUninitialized: 'Forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified.'
It appears that both options are for saving unmodified sessions. What's the difference?

I thought I would start off with a basic answer, my bit of understanding so far, and improve it together. Important question been 'dead' for too long.
From this I understand the difference is:
(Unmodified 'state' is different to uninitialized state)
resave: For any request made
Nothing in the session needs to change (no login etc).
Change of session required (logged in)
"Forces session to be saved even when unmodified"
saveUninitialized: Is about the state of the session, if its still in the uninitialized state.
Not modified only, nothing in the session needs to change (no login etc).
"Forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified."

Basically, a session is saved in the store only when it is modified; if you add, delete or edit a session cookie (eg: req.session.test = 'some value'). If you want all the sessions to be saved in store, even if they don't have any modifications go with saveUninitialized: true.
Now, re-saving also happens only when session variables/cookies changes. If you want to save then always go ahead with resave: true

Related

Express session, how do I get the session after posting? I see the session ID in browser under cookies, but it's undefined in request object?

Sorry guys, I'm really new to sessions and cookies and I'm trying to understand the mechanism behind it. I wanted to add register/login to my simple website and in order to do I need to understand web authentication and I really think I will have tons of questions regarding this topic.
Initially, I have register page that sends info after clicking submit button to a node server using express.
I'm trying to see what happens, so I've created a session in post route, it's created in the browser (connect.sid), then I commented out the part that creates that session and just tries to redisplay the session object, but it's undefined, but I still can see the session in the browser's cookies section, so what's going on? Thanks
app.use(session({
secret:"my test secret",
cookie:{},
resave:false,
saveUninitialized:false
}))
app.post("/register", (req, res) => {
req.session.usertest = "testsession_hardcodedvaluefornow";
console.log(req.session.usertest); // -> this is okay when above line to create is uncommented
//but when I comment the session assignment, it becomes undefined?
res.send("In register...");
})
I can see the session cookie even after commenting out the create session and posting over and over.
connect.sid s%3A_TahsTv0xhY-iHIdjDRblYJ_aZZ5oiSd.do7JcOGR1FaXPcFFIQ6hg5AW%2B0XVsYwIRO8vndyjDzs
req.session.id produces a different value (not undefined) even if I delete my session in the browser, so not sure where that comes from.
There is no "usertest" key in the session object, therefore it is undefined. The reason it's not undefined when you uncomment that line is because you create that key yourself in that instant with that line.
You can get the whole session object by using req.session, the session id by using req.session.id and the session cookie by using req.session.cookie.
Edit
To further clarify: a session will be made for every connected client. That is why you can see the cookie in the browser. That has no meaning however, it's just a way to uniquely identify that client (without actually telling you who that client is). Any information about that session (whether they're logged in, user id,...) needs to be stored in a session store. Express-session will use memory store by default, if the server restarts all that information will be lost, which is why that key doesn't exist. In order to preserve that information it has to be stored in a persistent session store. More information on session store implementations for express-session and how to use them can be found here: https://www.npmjs.com/package/express-session
As for the cookie values you get, those are the default ones set by express-session since you haven't set any yourself. You can change the maxAge to let it expire (or set it so 10 years or more for a more persistent session), you can specify a domain to which that cookie belongs, you can set it to secure (to only allow it over secure connections, e.g. https) and httpOpnly is by default true. httpOnly cookies cannot be accessed/altered by the client (although you can see them in the browser), do not set this to false.

Store cookies only for users who agreed to terms

To comply with GDPR without an annoying cookie banner, I would like the public pages on my website to not store cookies. To facilitate the journey of registered users, I would like to use flash messages. The problem is that these two seem incompatible, as setting sessions:
const session = require('express-session');
// Initialize mongodb session storage to remember users.
const store = new MongoDBStore({
uri: config.mongoUri,
// The 'expires' option specifies how long after the last time this session was used should the session be deleted.
// Effectively this logs out inactive users without really notifying the user. The next time they attempt to
// perform an authenticated action they will get an error. This is currently set to 3 months (in milliseconds).
expires: max_session_ms,
});
// Enable sessions using encrypted cookies
app.use(
session({
cookie: {
// Specifies how long the user's browser should keep their cookie, probably should match session expiration.
maxAge: max_session_ms,
sameSite: "strict",
},
store: store,
secret: config.secret,
signed: true,
resave: false, // Unknown effect. See https://github.com/expressjs/session#resave
saveUninitialized: false, // Save only explicitly, e.g. when logging in.
httpOnly: true, // Don't let browser javascript access cookies.
secure: config.secureCookies, // Only use cookies over https in production.
})
);
and flash messages with:
const flash = require("express-flash"); // Disabled to avoid cookies.
app.use(flash());
stores a cookie in the browser with an empty flash message for public pages. I don't think server-side only flash messages exist (see Server-side only flash messages (no cookies) ). I tried setting res.locals but it gets erased between redirects.
Is it possible to store cookies only for visitors who agreed to the terms in the logged-in area of the website and not for visitors in general?
3 remarks about your question :
requesting consent is not based on GDPR, it's requested by EU directive 2002/58/CE
this directive states explicitly that you don't need to request consent if you are storing a session on user's browser
storing a cookie or a flash is the same from EU directive's point of view, you can't avoid requesting consent in the case it's required by replacing cookies by anything that writes data in user's browser
if the rules are not clear for you, check the CNIL's page (French data authority protection) for example : https://www.cnil.fr/fr/nouvelles-regles-cookies-et-autres-traceurs-bilan-accompagnement-cnil-actions-a-venir
EDIT :
For everyone, to clarify when consent is needed, it's best you read the text of the directive directly it's very clear (article 5.3 directive ePrivacy 2002/58) :
Member States shall ensure that the use of electronic communications networks to store information or to gain access to
information stored in the terminal equipment of a subscriber or user
is only allowed on condition that the subscriber or user concerned is
provided with clear and comprehensive information (...) about the purposes of the processing,
and is offered the right to refuse such processing by the data
controller. This shall not prevent any technical storage or access for
the sole purpose of carrying out or facilitating the transmission of a
communication over an electronic communications network, or as
strictly necessary in order to provide an information society service
explicitly requested by the subscriber or user.

Understanding Express session in NodejS

I was trying to comprehend express-session from the docs and I am unable to get some points
Consider this code, which I found from a repo
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'aaabbbccc',
store: new MongoStore({
url: MONGO_URI,
autoReconnect: true
})
}));
Now, I probably get what is happening here but still just to confirm
resave: true according to the doc will mean that it will force to save session back to the session even if it hasn't changed. Okay Cool? But why would someone force to save a session when it isn't changed and what difference will make it make?
saveUninitialized: true Here we are storing the session for non-logged in user as well?
And Finally if someone could explain this line of code as well (which I am unable to comprehend)
store: new MongoStore({
url: MONGO_URI,
autoReconnect: true
})
Moving on, In the above code, the author of the repo isn't storing the session in the cookie? and is just storing the cookie identifer?
And lastly, In the description they have mentioned/talked about cookie.httpOnly, cookie.expires and cookie.domain
Now, I understood their functionality but am unable comprehend their implemention, so if anyone could showcase implementation for any one of them?
These are my understandings. I might be wrong.
May be resave is used for certain storage driver to keep session alive!? I don't have anything in mind right now.
saveUninitialized is true means, a session will always be created. Experiment: Create a simple express server. Configure express-session and keep that value true. Don't create any session manually. Hit any endpoint of your server from browser. Open developer options and look for cookies. You will see a cookie has generated. Now, remove the cookie. Change the value to false and hit the endpoint again. No cookie will generate this time.
If you don't mention any store then all sessions will be stored in MemoryStore which is build only for development purpose. So in production you should always use some sort of persistent storage. There are a good numbers of storage options available.

is it reasonable to get sessionid from url other than cookie? something about express-session

I have some domain( maybe change very frequently), and two stable domain(e.g. auth.aaa.com, api.aaa.com).
Since express-session(https://www.npmjs.com/package/express-session) default get sessionid from cookie, but when crossing domain,ajax won't send cookie( I don't want to use something like Access-Control-Allow-Credentials ).
I want to add the sessionid to the querystring, and forge a cookie before express-session middleware.
app.use(function(req,res,next){
var ss = req.query.ss;
if(ss){
var signature = require('cookie-signature');
var cookie = require('cookie');
var signed = 's:' + signature.sign(ss, "secret");
var data = cookie.serialize('jsessionids', signed);
req.headers.cookie = data;
}
next();
})
app.use(session({
name:'jsessionids',
store: new redisStore({
host:config.redis.host,
port:config.redis.port,
pass : config.redis.password,
db: config.redis.database
}),
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
secret: 'secret'
}));
is it reasonable? or any suggestion else?
It is generally not advisable to add the session as a query parameter, you have to jump through lots of hoops to get them to near the same level of security as cookies.
The main problem is that it is much more vulnerable to session fixation or session hijacking, which is where an attacker can steal and use another user's session.
Some key points to take into consideration
Query parameters are stored in browser history, bookmarks and referrer headers (just to name a few) which
could allow an attacker to use another users session on a shared
environment. Query string based sessions are much easier to leak outside their intended scope.
Cookies have better security mechanisms built in such as the
httpOnly flag which makes the cookies in-accessible to JavaScript
(whereas query strings are always accessible). The secure flag makes
sure that cookies are only sent over a secure connection (You could
perhaps use HSTS to help guard against MITM attacks for query string).
A user who share a link with their sessionID in the query string
which would allow any other user to assume their identity.
If you do decide to use the sessionID in the query string make sure you set an expiration time for the session and always to use TLS to securely transmit the session (same applies to any authentiction method).
Saying that, If you can avoid using query string based sessions, I would advise you do.

Persistent user sessions in node.js using Google Authentication

I followed a tutorial to include Google authentication for my web application using the passport-google-oauth module. The server.js file has the following lines of code:
app.use(express.session({ secret: 'victoriassecret' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
In addition, I find that the application automatically logs the user out after some time. Passport is configured in a separate file that is imported in server.js. Is there some way I can increase the time before the user is logged out, or even better, not log him out until he clicks on the logout button? Also, what is the session secret?
1) You can define the maximum life-time of a session cookie ( and concurrently the time before a user is automatically logged out ) using the maxAge option of the cookie parameter like this :
app.use(expressSession({ cookie: {maxAge: 10000} , secret: 'victoriassecret'}));
According to this maxAge value ( 10000 ) the cookie's maximum life-time will be 10.000ms(10 sec).
(obviously you need a much bigger value than this)
Thus,you can increase the maxAge value in order to suit your needs and make sure user does not get logged out until he decides so, pressing the Logout button.
2) The session secret is a random string used to hash the session with HMAC ( more on HMAC : here) in order to protect the session from being highjacked.

Resources