Node js express-session creating new session id every time I refresh or access the page
Asked Answered
U

2

7

I am facing the issue : on every request new sessionID is getting created. Can someone throw light at this ?

Versions I am using:

NODE VERSION: v6.10.3 NPM VERSION: 3.10.10 [email protected] [email protected]

Also what is the default value for maxAge if I am not setting the cookie specifically ? Not sure if its required.

Do you see any issue with the code below ? Please assist as I am stuck.

      var app = express();
        app.use(express.static(path.join(__dirname, 'landing')));
        app.use(bodyparser.json());
        app.set('trust proxy', 1) // trust first proxy
        app.use(session({
        secret: 'keyboard cat',
        resave: false,
        saveUninitialized: true,
        cookie: {secure: true}
    }))

    app.get('/', function (req, res) {
        res.sendFile(path.join(__dirname, 'landing', 'index.html'));
    });


    var contextPath = '/myportal';

    //UI url
    app.get(contextPath, function (req, res) {
        var reqValues;
              logger.info("req sessionID is :::" + req.sessionID);
           // do something
                } 
        app.use(express.static(path.join(__dirname, 'build'))); //react UI path
        res.sendFile(path.join(__dirname, 'build', 'index.html'));
  }    

    //health check url
    app.get(contextPath + '/health', function (req, res) {
        logger.info("env is " + env);
        logger.info("myportal health is ok");
        res.send('Health Ok!\n');
    });
Unsex answered 3/7, 2017 at 23:0 Comment(6)
Are you read manual?Woodsman
Yes I have gone through the doc and that's how I was trying but unfortunately its not working for me. Wondering what I am missing here.Unsex
You must use https-express.Woodsman
thanks Aikon, yes I am already using that since I am trying to deploy it on the server where https is enabled. sorry code was growing big so could not provide those details in the initial questionUnsex
My application is single sign on protected so SSO is providing me the unique session id which I can use instead of relying on the node js session idUnsex
PALLAMOLLA SAI described it correctly - I was facing the same problem. To summerize it to nutshell - you probably used post which, by default doesn't send the cookie. Either use get, or make a post request with the appropriate header which will send the cookie. You may need to verify that cookie-parser is also defined in your node serverBlackman
H
8

If still anyone is looking for an answer. (After working a lot following code worked for me. correct me if I am wrong)

REASON: express session stores sessionID in cookie and it will set that cookie in frontend(browser and you can see that cookie called connect.sid in browser) from backend(server). Whenever any request comes from browser first it will check for that cookie(in which sessionID is stored.) If it finds the cookie it doesn't create new session otherwise it will create again a new session.(you can check it by logging req.sessionID in requests)

SOLUTION: To overcome this for every request we are making from frontend(browser) we have to send that cookie to backend(server). Server will automatically parse cookie and doesn't create any new session for every request.

I was using axios for request calls in which for every request I was adding {withCredentals:true} so that browser can send cookies to backend server(automatically). Following code was worked for me.

app.js

require('dotenv').config({path:'./config.env'});

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors=require('cors');
const uuid = require('uuid/v4')
const cookieParser = require('cookie-parser');
const session = require('express-session');
var FileStore = require('session-file-store')(session);

app.use(cors({
 origin:[process.env.ORIGIN],//frontend server localhost:8080
 methods:['GET','POST','PUT','DELETE'],
 credentials: true // enable set cookie
}));

app.use(cookieParser(process.env.SESSIONSECRET)); // any string ex: 'keyboard cat'
app.use(session({
  secret: process.env.SESSIONSECRET,
  store:new FileStore,
  cookie:{
    maxAge:36000,
    httpOnly:false,
    secure:false // for normal http connection if https is there we have to set it to true
    },
  resave: false,
  saveUninitialized: true
})) 

app.use(function(req, res, next) {

res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
res.header("Access-Control-Allow-Origin", process.env.ORIGIN);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-   Type, Accept, Authorization");
next();
});

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

// rest of code is your mongo connection

axios rest calls::

 axios.defaults.withCredentials = true;
 axios.get('http://localhost:8080/getDetails',{
           headers:{
                    withCredentials:true,

                   }
  });
Hanoi answered 9/4, 2019 at 17:12 Comment(2)
I've done exactly as you've done. Session id still unique with every request.Hypothesis
For me the change I needed was saveUninitialized: true, though not sure how well this will do in production as it has known issuesOlney
B
2

it's a cookie problem

create a env for development and production

const SessionCookie = process.env.NODE_ENV == "dev" ? {
    secure: false,
    sameSite: "lax",
    maxAge: 1000 * 60 * 60 * 60 * 24 * 2//2 day
} : {
    secure: true,
    sameSite: "none",
    maxAge: 1000 * 60 * 60 * 60 * 24 * 2//2 day
}

app.set('trust proxy', 1) // trust first proxy
app.use(expressSession({
    name: "test-me-esc",
    secret: 'keyboard cat',
    store: new FileStore({}),//change your store here.
    resave: false,
    saveUninitialized: false,
    cookie: { ...SessionCookie } as any
}))

this will work on localhost: chrome, brave, firefox.

Bessbessarabia answered 30/4, 2022 at 23:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.