cookie.maxAge goes back to originalMaxAge value on each request - node.js

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.

Related

Why is the express session cookie not stored in the browser's cookie storage on production but is working on localhost/development? (express + react)

I have created a test app, my react app is deployed at vercel and my node express is deployed at render.com. I set the same domain on both to solve cross-site cookie problems (app.mydomain.online)(api.mydomain.online). Now no error is showing when I view the cookie in the header but still when I check the cookie storage it is still not stored or not being saved at the browser's cookie storage.
server is created via npm init.
react is created via npm create-react-app.
as of now this is my sample code.
server
const express = require("express");
const cors = require("cors");
const session = require('express-session');
const app = express();
require('dotenv').config();
const PORT = process.env.PORT;
app.use(express.json());
app.use(cors({
origin: 'https://app.myDomain.online',
methods: ["POST", "PUT", "GET", "OPTIONS", "HEAD"],
credentials: true
}));
const oneDay = 1000 * 60 * 60 * 24;
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true, sameSite: 'none' }
}));
app.get('/createSession', (req, res) => {
req.session.user = 'user';
res.send('new session is created');
});
app.get('/', (req, res) => {
res.send('get sess')
});
app.get('/getSession', (req, res) => {
if(req.session.user){
res.send('active');
}else{
res.send('not active');
}
});
app.listen(PORT, () => {
console.log(`The server is running on port ${PORT}`);
});
react
import React from 'react'
import { useEffect } from 'react';
import Axios from 'axios';
function Test() {
useEffect(() => {
Axios.get(' https://api.myDomain.online/createSession',
{ withCredentials: true }
);
}, []);
return (
<div>Test</div>
)
}
export default Test;
From the documentation for express-session...
cookie.expires
Specifies the Date object to be the value for the Expires Set-Cookie attribute. 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.
The docs go on to prefer the maxAge property to control this. Choose a time frame that makes sense for your application. For example, 1 week...
app.use(
session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: { secure: true, sameSite: "none", maxAge: 7 * 24 * 60 * 60 * 1000 },
})
);
I have already fixed it a few days ago, I found out that the reason why the cookie was blocked was that the cookie has exactly the same domain as the server or probably has the same link address. As the domain of the server is api.myDomian.online, the cookie domain can't be api.myDomain.online. Not sure if that is the direct reason, but somewhat similar I think as the code works by setting a new domain to the cookie. I just removed the subdomain of the cookie like .myDomain.online and it works. here is my configuration. My backend is already deployed at aws when I test it but it could also work in render. I will try it out later on.
This is my new configuration
const oneDay = 1000 * 60 * 60 * 24;
const APP_SESSION = session({
secret: 'secrete',
resave: false,
saveUninitialized: true,
name: 'session',
cookie: {
secure: true,
sameSite: 'none'
maxAge: oneDay,
domain: '.domain.com'
}
});
Haven't tried to remove sameSite if it will still work.

Express session resets on every request

I have a vue frontend on localhost:8080 and a server at localhost:1234
I am using no https.
Every time the vue app switches pages or gets reloaded, the Session resets. I've followed various solutions on the web, like these:Express session resets session on every request and Session keeps resetting on Node.js Express
However to no avail.
This is my session config:
// app.set('trust proxy', 1 );
app.use(session({
secret: sessionServerToken,
resave: true,
saveUninitialized: true,
cookie: {
// Session expires after 1 hour of inactivity.
expires: 60 * 1000 * 60,
// sameSite: 'none',
secure: false
}
}));
and this is my auth code:
router.post('/auth', (req, res) => {
console.log(req.body);
const session = req.session;
AuthManager.authenticate(req.body.user, req.body.pass).then(response => {
session.loggedIn = true;
session.userID = response.user.id;
res.status(200).send(response);
res.end();
}).catch(response => {
res.status(response.statusCode).send({ message: response.message });
});
});
Cookies won't be shared between different origins. Session data is not shared to the frontend app that's why it acts like the session is being reset.
If you build your Vue app and serve it over Express you won't face this problem and the session will be shared as expected.
However for development, it will be annoying, you can proxy the front-end app over Express.
As a minimal example, you can try the code below. Run your Vue app as you normally do and then run the server with the following
const express = require('express');
const session = require("express-session");
const proxy = require('express-http-proxy');
const app = express();
app.use(
session({
secret: 'keyboard cat',
cookie: {
maxAge: 60000
},
value: 0
})
);
app.get('/api', (req, res) => {
req.session.value ++;
res.json({
session: req.session.value
});
});
app.use(proxy('http://127.0.0.1:8080'));
app.listen(4001, '0.0.0.0', () => {
console.log('Server is running at http://127.0.0.1:1234');
});
Vue app content will be available on http://127.0.0.1:1234 and if you navigate http://127.0.0.1:1234/api and refresh several times you will see the session value is present and not resetting.

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;});
});

How to exclude routes from renewing express cookie expiration date

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);
});

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