How to exclude routes from renewing express cookie expiration date - node.js

Using express js with express-session I have this main classic session middleware which defines the cookie's maxAge to one hour.
var express = require('express');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var ExpressServer = express();
ExpressServer.use(
session(
{
secret : 'secret',
// Forces session to be saved even when unmodified
resave : false,
rolling : true,
// Forces session to be saved even when unmodified
saveUninitialized : true,
// Controls result of unsetting req.session (through delete, setting to null)
unset : 'destroy',
cookie: {
path: '/',
proxy: secureCookie,
secure: secureCookie,
httpOnly: true,
maxAge: 1000 * 60 * 60
},
store: new RedisStore(
{
client: RedisClient
}
)
}
)
);
However, I have some routes which are called periodically (every 30 seconds) from the client to the server, let's say one of them is:
ExpressServer.get(
'/periodic',
function (req, res, next) {
//doSomthing()
}
since this route is called periodically from the client, I need that it won't cause a renewal of the cookie's expiration date (in case the user leaves his browser open) and leave the current expiration date (from the last not-periodic route call)
How can I achieve it?

Simply put the ExpressServer.get('/periodic') call before the ExpressServer.use(session()) call. Or you can do something like:
var url = require('url');
var normalSessionOpts = {
secret : 'secret',
// Forces session to be saved even when unmodified
resave : false,
rolling : true,
// Forces session to be saved even when unmodified
saveUninitialized : true,
// Controls result of unsetting req.session (through delete, setting to null)
unset : 'destroy',
cookie: {
path: '/',
proxy: secureCookie,
secure: secureCookie,
httpOnly: true,
maxAge: 1000 * 60 * 60
},
store: new RedisStore(
{
client: RedisClient
}
)
};
var nonRollingSessionOpts = Object.assign({}, normalSessionOpts, { rolling: false });
var normalSession = session(normalSessionOpts);
var nonRollingSession = session(nonRollingSessionOpts);
ExpressServer.use(function (req, res, next) {
var parsedUrl = url.parse(req.url)
return parsedUrl.pathname === '/periodic'
? nonRollingSession(req, res, next)
: normalSession(req, res, next);
});

Related

CSRF with fastify session cookies

I have a fastify session plugin that creates user sessions and manages them in postgres, but i want to make sure that i have all my sessions protected from CSRF. Im looking at the fastify-csrf plugin and im not exactly sure how to properly implement this. Do i need to generate the csrf token only when the session cookie is first generated or on all requests?
session plugin:
const cookie = require('fastify-cookie');
const session = require('fastify-session');
const csrf = require('fastify-csrf');
const pgSession = require('connect-pg-simple')(session);
const fp = require('fastify-plugin');
/**
* #param {import('fastify').FastifyInstance} fastify
*/
const plugin = async (fastify) => {
// All plugin data here is global to fastify.
fastify.register(cookie);
fastify.register(csrf, { sessionPlugin: 'fastify-session' });
fastify.register(session, {
store: new pgSession({
conString: process.env.DATABASE_URL,
tableName: 'user_session', // Defaults to 'session'
}),
secret: process.env.SESSION_SECRET,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: 86400 * 1000, // 1 day expiration time
},
});
<!-- This is from the documentation, should this only be applied to the /login route when the cookie is generated? When do i verify that the cookie has not been tampered with?
fastify.route({
method: 'GET',
path: '/',
handler: async (req, reply) => {
const token = await reply.generateCsrf();
return { token };
},
});
// Add the user object to the session for later use.
fastify.addHook('preHandler', (req, reply, next) => {
if (!req.session) req.session.user = {};
next();
});
};
module.exports = fp(plugin);

How to create a session for user system in node.js

I am trying to create a session for my system of users but I do not manage in any way to implement the sessions and it returns me that they are not defined.
I am currently using express-session, body-parser and cookie-parser.
I have tried to implement the session variables from my app.js file, invoke it to my access file and I still get an error of variable without defining
my varaibles of app.js
app.use(cookieParser());
const redis = new connectRedis(session);
app.use(session({ store : new redis, saveUninitialized: true, resave: true, secret: 'it*SFVse', ttl : 3600, cookie: { maxAge: 3600000 * 24 * 7 } }));
app.use(connectFlash());
my post form
if (bcrypt.compareSync(password, result[0].password)) {
message = 'Welcome';
req.session.user = 1;
res.render('index.ejs', {
message,
title: "Login",
});
}
my index.js
getIndex: (req, res) => {
if (typeof req.session.user === 'undefined') { session = 'no session' } else { session = "session"; }
res.render('index.ejs', {
title: "Login",
message: '',
session
});
}
TypeError: Assignment to constant variable.

cookie.maxAge goes back to originalMaxAge value on each request

I'm setting maxAge to 30minutes. after login i didn't make any event in my application. but every five minutes i'm making GET api call to get count of records. After every api call my cookie.maxAge value reset to originalMaxAge, so my application not get session expire.
var express = require('express');
var router = express.Router();
var app = express();
app.use(session({
name: 'rootElementId',
secret: jwt_secretkey,
store : sessionStorage,
cookie: { path: '/', httpOnly: true, maxAge: null },
saveUninitialized : false,
resave: false,
rolling: false,
genid : function(req){
return "SEC_KEY"
}
}));
router.use('/getCount', function(req, res){
var count = JSON.parse(JSON.stringify( req.session.mgmtResponse ));
res.send('{"count":count}');
});
router.use('/getData', function(req, res){
req.session.cookie.maxAge = 30 * 60000;
req.session.touch();
});
Note: In Nodejs version 9.8.0 its worked fine. After update Nodejs version 8.11.1 i'm facing this issue.

How do I share sessions with express and websockets using connect-sqlite3?

I need to share sessions between express-session (v4) GET requests and WebSockets on('connection') using connect-sqlite3.
The following basic setup without sqlite3 (from Azmisov's answer at ExpressJS & Websocket & session sharing) works:
global.app = express();
var sessionParser = require('express-session')({
secret:"some secret",
resave: true,
saveUninitialized: true
});
app.use(sessionParser);
app.get('*', function (req, res) {
req.session.working = "Yes";
});
wss.on('connection', function connection(ws, req) {
sessionParser(req, {}, function(){
console.log("New websocket connection: Working = " + req.session.working + ".");
});
});
However, when I try to implement this with connect-sqlite3:
var sessionParser = require('express-session');
var SQLiteStore = require('connect-sqlite3')(sessionParser);
app.use(sessionParser({
store: new SQLiteStore({dir:configuration.data_dir, db:'sessions.s3db', table:'sessions'}),
secret: 'some secret',
resave: false,
saveUninitialized: true,
cookie: {
maxAge: configuration.session_cookie_maxage_ms,
name: 'shadowlands'
},
}));
app.get('*', function (req, res) {
req.session.working = "Yes";
});
wss.on('connection', function connection(ws, req) {
sessionParser(req, {}, function(){
console.log("New websocket connection: Working = " + req.session.working + ".");
});
});
In wss on('connection') at sessionParser(req, {}, function(){ ...), I get:
express-session deprecated undefined resave option; provide resave option; provide resave option.
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option; provide saveUninitialized option.
express-session deprecated req.secret; provide secret option.
This error still occurs if I change to:
sessionParser(req, {secret: 'some secret', resave: false, saveUninitialized: true}, function(){
The error goes away if I take out "req":
sessionParser({secret: 'some secret', resave: false, saveUninitialized: true}, function(){
But then the sessionParser function does not get called, and req.session.working is not shown in the console.
The session does actually get saved to the sqlite3 database.
Any help much appreciated, thanks!
Eric T.
I managed to fix it using cookie-parser and cookie in the websocket on('connection').
Note that I had to declare MySessionStore outside the app.use() so that I could perform a get() on it.
var sessionParser = require('express-session');
var SQLiteStore = require('connect-sqlite3')(sessionParser);
var MySessionStore = new SQLiteStore({dir:configuration.data_dir, db:'sessions.s3db', table:'sessions'});
var cookieParser = require('cookie-parser');
var cookie = require('cookie');
app.use(cookieParser())
var sessionParser = require('express-session');
app.use(sessionParser({
resave: true,
saveUninitialized: true,
secret: "some secret",
store: MySessionStore,
cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } // 1 week
}));
// ============
app.get('*', function (req, res) {
req.session.working = "Yes";
});
// ============
wss.on('connection', function connection(ws, req) {
var got_cookie = false;
var cookies = cookie.parse(req.headers.cookie);
var sessionID = cookieParser.signedCookie(cookies['connect.sid'], "some secret");
MySessionStore.get(sessionID, function(err, sess) {
functions.write_log("session", "WSS: New websocket connection: " + "Working = '" + sess.working + "'.");
got_cookie = true;
});
// Optional, if you need a synchronous return from the function.
require('deasync').loopWhile(function(){return !got_cookie;});
});

Why can't change session's expires duration setting in connect-mongo + express.js?

app.js
app.use(express.cookieParser('your secret here'));
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sample);
var MongoStore = require('connect-mongo')(express);
var sessionExpireTime = 10000000; // 10000 sec
var sessionStore = new MongoStore({
mongoose_connection: mongoose.connection[0],
db: config.db.name,
clear_interval: sessionExpireTime / 1000 // second
});
app.use(express.session({
secret: 'your secret here',
store: sessionStore,
cookie: {
httpOnly: false,
maxAge: new Date(Date.now() + sessionExpireTime) // millisecond
}
}));
app.get('/', function(req, res) {
if (req.session.user) {
res.render('index', {title: 'Welcome!'});
} else {
res.redirect('/login');
}
});
app.get('/login', function(req, res) {
res.render('login', {title: 'login'});
});
app.get('/auth', function(req, res) {
req.session.user = {name: 'John'};
res.redirect('/');
});
When call "/login" then redirect to "/" page.
And document created in "sessions" of the MongoDB collection.
But req.session.user is destroyed from req.session after 10 seconds.
It will return to the login screen when you reload the page.
I am aware that interval to monitor clear_interval of connect-mongo is not expired the cookie.
Will there the necessary settings of something in order to change expire duration of req.session.user?
Thank you I received your relationship to unfamiliar my English...
The maxAge property should be an absolute number of milliseconds, not a date:
cookie: {
httpOnly: false,
maxAge : sessionExpireTime
}
There are also some other issues with your code:
mongoose_connection: mongoose.connection[0]
That should be mongoose.connections[0] (or mongoose.connection, which is the same).
The clear_interval property doesn't seem to exist in (at least the current version of) connect-mongo. The way it expires sessions is using MongoDB's ttl feature (which runs once per minute).

Resources