Controlling Session Start with LocomotiveJS - node.js

I know it is possible to control session start with express and connect middleware. Like suggested here: Controlling Session Start with express and connect middleware
Is it possible to control session start with LocomotiveJS?
I don't want to start session for every user - I just want to start it when user successfully logs in.
I'm already storing session in MongoDb (myabe in the future I will use Redis) and creating not required session for every user which enter the page seems to be a waste of resources.

I just found the solution:
Maybe LcomotiveJS itself does not support it directly, but it can be easily implemented using Express (and Locomotive is on top of it).
Instead of declaring session as:
this.use(express.cookieParser());
this.use(express.session({
secret: '123qwemax',
cookie: {maxAge: 60 * 60 * 1000},
store: new MongoStore({
url: 'mongodb://localhost:27017/tests'
}),
}));
Declare your session as:
this.get(/^\/login\/.*/, express.cookieParser());
this.get(/^\/login\/.*/, express.session({
secret: '123qwemax',
cookie: {maxAge: 60 * 60 * 1000},
store: new MongoStore({
url: 'mongodb://localhost:27017/tests'
}),
}));
This way session will start any time we will go to /login/.* pages.
I don't know why this.all was not working...

Related

Express-session not deleting previous sessions

I am currently working on a new project and I use sessions with the express-session library.
Here is the code where I set up the session:
const IN_PROD = process.env.MODE==='production'
app.use(session({
name: 'sid',
secret: 'asecret',
store: new MongoStore({
mongooseConnection: mongoose.connection,
collection: 'sessions'
}),
saveUninitialized: false,
resave: false,
cookie: {
sameSite: true,
secure: IN_PROD,
expires: new Date(new Date().getTime() + 1000 * 60 * 60 * 24)
}
}))
Imagine the following steps:
1) My server sends a session id (sid=A) in a cookie to my client.
2) The client manually deletes the cookie
3) At the next request, the client sends another session id (sid=B)
Is it normal that both A and B cookies are stored in the database and the first one is not overridden?
It is normal. It is up to either you or the session store you use to clean up older sessions.
If you look at the MongoStore() documentation, you will see that it has several features related to automatic removal of session objects.
Here's one example:
// connect-mongo will take care of removing expired sessions, using defined interval.
app.use(session({
store: new MongoStore({
url: 'mongodb://localhost/test-app',
autoRemove: 'interval',
autoRemoveInterval: 10 // In minutes
})
}));
Keep in mind that at the express-session level, a session is just a blob of data associated with a cookie. Any time a browser makes a request to your server and no session cookie exists, a new session cookie is created and a new express-session object that is connected to that new cookie.
If the user then deletes that cookie and connects to your server again, express-session has no idea that this browser is the same browser as the previous session. The original cookie is the only way it could know that and the cookie is now gone. So, express-session just sees a new browser connecting to your server that doesn't have a session cookie so it creates a new cookie and then creates a new session object to go with it.
Any association of a logged in user with an express session is done at your application level (by putting user-identification information into the session object) and express-session is not aware of that at all.

Express session not setting session

I am using express sessions on node.js to store user sessions. I have deployed to an AWS EC2 instance and it works when I call it directly over HTTP. To make the ec2 instance HTTPS, I use AWS CloudFront but then my client cookies are not being set anymore from express session.
I cannot just make the node server directly HTTPS because my SSL certificate is on ACM (which does not allow me to download it).
The express session middleware is shown below. Am I setting this up correctly for HTTPS requests?
let sessionMiddleware = session({
store: new redisStore({
client: redisClient,
ttl: 365*24*60*60
}),
saveUninitialized: false,
resave: false,
secret: "Shh, its a secret!",
cookie: {
httpOnly: false,
secure: true,
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000)
}
});
I fixed the problem by setting the the express session middleware's proxy flag to true. Hope this helps someone.

How to disallow TTL refresh for sessions stored through Express-session?

I have a couple requirements around session handling and I'm having trouble enforcing one.
Sessions need to:
Expire in 30 mins if user has been inactive
Expire in 8 hours from when user first logged on regardless of activity.
I was able to configure item 1 but not item 2. Every time a user is browsing application, the cookie is updated (with time+30mins) and sent back to the browser but at the same time the session storage TTL is also refreshed. The last part is what I need to stop.
I believe the TTL refresh is implemented as a feature from express-session. Session.touch() is called by the middleware but is there a setting that'll remove this action?
The stack:
Node, express, express-session, connect-redis for session storage.
The configuration:
app.use(session({
store: new RedisStore({
client: redis_client,
ttl: 28800 // 8 hours
}),
secret: config.redis_session_secret,
resave: false,
saveUninitialized: false,
cookie: {
path: '/',
httpOnly: true,
secure: false,
maxAge: 30 * 60 * 1000 //mins * seconds * milliseconds. session cookie will expire every 30 mins
},
rolling: true
}));
I don't think option 2 is a supported feature of express session. So, instead you can just add a property to each session that indicates the time it was started and then every 10 minutes or so (probably on an interval timer), query for all sessions where that property is older than 8 hours and remove them from the database.
You could instead implement middleware that checks the session expiration on every request and removes the session if it find the session is older than 8 hours.
You should be aware that implementing this behavior could cause a user to lose their session in the middle of using your app (which is why it is not typically implemented this way).

My Node.js web app establishes new session every time I reopen the browser

Every time I close all the browser windows and then open the web app again, a new session is established, that means I have to authenticate again.
For your reference, I use express#4.14.0 as the web application framework, express-session#1.14.1 + connect-mongo#1.3.2 as middleware to store the sessions and passport#0.3.2 for authentication.
Below is the code for cookie and session configuration:
// CookieParser should be above session
app.use(cookieParser());
// Express MongoDB session storage
app.use(session({
resave: true,
saveUninitialized: true,
name: config.sessionName,
secret: config.sessionSecret,
store: new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
})
}));
The "old" session stored in MongoDB still has two weeks to expire.
It seems like the Node.js application cannot recognize the "old" session from browser, therefore create a "new" one and tell the browser to use the "new" one.
It does not happen occasionally, but always, so I believe there is something wrong in my web application.
Thanks to #Bradley, finally I figured out what's wrong.
This is my solution
app.use(session({
cookie: {
maxAge: ms('14 days') // `ms` is a node module to convert string into milliseconds
},
resave: true,
saveUninitialized: true,
name: config.sessionName,
secret: config.sessionSecret,
store: new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
})
}));
For more information, please refer to https://github.com/expressjs/session#expires
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application.
That's why I encountered this problem.

Node/Express with connect-redis, how handle session expiry

I have a Node/Express application that use redis as session store.
I have a question concerning the handling of the expiry of the session.
I'd like have an active session until the browser is closed, so I didn't set a session expiration time.
Doing that the session cookie works fine, but I have a doubt about Redis.
It seems that the couple Key/Value stored in Redis DB never expire.
How is the right way to handle this?
There is a way to configure redis to destroy a value stored with a certain idle time?
Or is better set a TTL when the connect-redis is invoked inside the application?
Actual configuration of the session inside the application:
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore({port:6379, host: 'localhost'}),
secret: "my-secret-here",
resave: false,
saveUninitialized: true }));
Using Redis with express-session, you can use the touch() method from express-session to reset the TTL. So if you set a TTL when creating the session, do something like this on the routes where you don't want the session to expire:
api.get("/someRoute/", (req, res) => {
req.session.touch();
// Whatever else you need to do
res.sendStatus(200);
}
That will reset the TTL on Redis and prevent the session from expiring assuming the client is still hitting your API - I'm assuming that if the client doesn't interact with your API for long enough, that implies the browser is closed or otherwise finished using your app.
You can specify a ttl while creating the session store.
You can find more options in the readme.
app.use(session({
store: new RedisStore(options),
secret: 'keyboard cat',
ttl : 20 // ttl is in seconds. From the readme.
}));

Resources