Keep user sessions logged in on Node.js server restart - node.js

I am using express-session for a login system for users on my Node.js web application. My issue is that every time I make an update and restart the Node.js server, all the users are logged off which is not ideal behaviour (there are multiple users logged on via the local network and I would like to not have to log them back on each time there is a restart).
From my understanding I could use something such as connect-pg-simple (for reference I am using a postgres database with my node web app) to keep users logged in on server restart but I am unsure of how to implement this.
I know it would be something along the lines of:
app.use(session({
store: new (require('connect-pg-simple')(session))({
// Insert connect-pg-simple options here
}),
secret: 'secret',
resave: false,
saveUninitialized: true
}));
But I do not know what options to use or how to save the users session even on server restart.

Yes you are on the right track.
Open your database and create a table named session. See: https://github.com/voxpelli/node-connect-pg-simple/blob/HEAD/table.sql
Add the connect-pg-simple code like you posted
Pass the postgres pool you are using from node-pg.
const session = require('express-session')
const PGSessionStore = require('connect-pg-simple')(session)
const pg = require('pg')
const pool = new pg.Pool({
user: process.env.PG_USERNAME,
host: process.env.PG_HOST,
database: process.env.PG_DATABASE,
password: process.env.PG_PASSWORD,
port: process.env.PG_PORT
})
app.use(session({
store: new PGSessionStore({
pool: pool,
tableName: 'session'
}),
secret: process.env.COOKIE_SECRET,
cookie: {
secure: false,
httpOnly: true,
sameSite: true,
maxAge: 24 * 60 * 60 * 1000
},
saveUninitialized: true,
resave: false
}))

Your session is stored on the app runtime, so on refresh, it resets back every other data it might be holding at runtime on server restart

Related

How to avoid the server side session creation for every page

New sessions are created for every page, I'm setting the token in the server-side session after the login. But it is not available on the next page a new session is created on that page How to avoid this? The database disconnects after the API call on the page. Every time the database connection is made before calling the API. I require the token throughout the login.
src/index.ts
...
const session = require("express-session")
app.use(session({
name : 'Server_ID',
secret : 'something',
resave:false,
saveUninitialized: true,
rolling: false,
cookie: {
same site: true,
// secure: "development",
httpOnly: true,
secure: false,
maxAge:1000 * 60 * 10
}
}));
...
you must set credentials flag with your API call
for example if you're using axios, you do this:
axios.defaults.withCredentials = true;
with this approach cookie is going to sent along with your request call
make sure you have correct CORS settings too.

express-session not being saved locally but works in production

So I am running a node.js backend with a react frontend, and for some reason with this setup:
app.use(session({
store: new MongoStore({
mongooseConnection: mongoose.connection
}),
secret: process.env.SECRET_KEY,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7 * 2, // two weeks
secure: false,
httpOnly: false,
}
}));
I save the username using: req.session.username = username; which does save but then whenever I try to check the session on another page the username is gone.
Full source code: https://github.com/CTF-Cafe/CTF_Cafe/tree/master/backEnd
PS: it works in production completely fine, but not locally I tried with httponly false, and secure false. No change.
Any help appriciated
When you serve your frontend from your backend the session will be working because it has the same origin. However, for your local environment, you will be running React app in a different port, and the Express app would be also different. When a port is different it is already considered a different origin and cookies, sessions won't be shared.
You can proxy your frontend via the node app and this way you can have the same origin and your session will remain.
const proxy = require('express-http-proxy');
const app = express();
...
// Add after your routes
app.use(proxy('http://127.0.0.1:3000')); // assuming your Reacts runs on P3000
Check this answer too.

How do I set a session expiration date in redis node.js without maxAge?

I have this code:
const redisClient = redis.createClient({
host: 'localhost',
port: 6379,
ttl: 10
});
app.use(session({
store: new RedisStore({ client: redisClient });,
secret: 'some secret',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
sameSite: true,
maxAge: 60*1000
}
}));
And everything works as it should. After the maxAge expires, redis is also cleared. But if you delete maxAge and leave ttl, then redis will never be cleared, how to clear redis without specifying maxAge, because the user can change the value of the cookie maxAge to null, and then redis will never be cleared. Can I somehow specify the expiration time directly in redis and not in cookies? Or did I get something wrong? Thank you in advance.
As you can see in connect-redis docs under the ttl option - "If the session cookie has a expires date, connect-redis will use it as the TTL.".
So in you're case - both the cookie and the key in redis will be cleared on expiration.
And even if the client will somehow change the cookie expiration time, it won't effect redis (so the cookie might be sent over the HTTP request, but the server won't recognize it).
(You didn't mentioned which modules you're using, I'm just assuming its express-session and connect-redis)

req.session is undefined when running on Heroku(RedisToGo adds-on) but available when using redistogo url locally

I've deployed my front-end(React with Typescript) and backend (Nodejs with Typescript) to Heroku separately. I'm using express-session and connect-redis to maintain the user session, for which I'm using an external Redis service called Redistogo.
When I run my apps locally, req.session is present, and upon authenticating the user during login, I'm able to set the user's session in req.session.user. However, when running the backend on Heroku in the exact same way, req.session remains undefined.
if(process.env.NODE_ENV === 'production') {
this.app.set('trust proxy', 1)
const rtg = url.parse(process.env.REDISTOGO_URL);
const redisClient = redis.createClient(rtg.port, rtg.hostname);
redisClient.auth(rtg.auth.split(":")[1]);
this.app.use(session({
name: 'random_pur',
store: new RedisStore({
redisClient
}),
secret: 'meow',
resave: true,
saveUninitialized: false,
cookie: {
secure: false,
sameSite: false,
maxAge: 36000000,
httpOnly: false,
}
}));
}
So I'm not sure what I'm missing here - it doesn't give any problems on localhost. Any help would be appreciated. Thanks!

Socket.io page refresh

I am making a one to one chat application using socket.io and mongodb, whenever I refresh the page a new socket connection is formed, whenever user joins the chat he needs to refresh the page at the beginning then only it starts receiving messages. Can anyone tell me how to avoid it?
I am using express-session to store the session.
var sessionInit = session({
name: 'userCookie',
secret: '9743-980-270-india',
resave: true,
httpOnly: true,
saveUninitialized: true,
store: new mongoStore({
mongooseConnection: mongoose.connection
}),
cookie: {
maxAge: 80 * 80 * 800
}
});
app.use(sessionInit);
Maybe not the best thing to do but you can use
window.location.reload();
when someone joins the chat so they don't have to do it by themselves

Resources