Search code examples
node.jsexpresssessionpassport.jsexpress-session

Sharing Express Session Across Sub Domains


I have 2 apps, WEB and APP and they're hosted on different ports (locally) and different domains (publically) example:

  1. www.domain.com (WEB)
  2. app.domain.com (APP)

I'm trying to call the same login session on both apps, the code i have works great on my local machine (maybe because its the same hostname and ports dont break the session and count it as a new one)

When i try to push my code to production it doesnt work at all, the web session does not recognize the session that is set by the APP

the APP is where the session is set (it handles login).

The below code for session and cors is used on both web and app

const cors = require('cors')
app.use(cors());
app.use(cookieParser());

app.use(
    session({
        resave: true,
        saveUninitialized: true,
        secret: process.env.SESSION_SECRET,
        cookie: { maxAge: 1209600000 }, // two weeks in milliseconds
        store: new MongoStore({
            mongooseConnection: mongoose.connection,
            autoReconnect: true
        })
    })
);

Once a user is logged in from the APP, i want that session to be mantained and recalled via the WEB package. So that i can dynamically change the website experience as well.

Solution

@theusguy was right about adding the domain param. There were more issues that i was facing that needed to be solved

Headers.Host my nginx was not configured properly so the host name was 127.0.0.1:3000 to fix that i added the following config to the conf

location / {
proxy_pass http://127.0.0.1:3021;
proxy_http_version 1.1; //this was missing
proxy_set_header Upgrade $http_upgrade; //this was missing
proxy_set_header Connection 'upgrade'; //this was missing
proxy_set_header Host $host; //this was missing
proxy_cache_bypass $http_upgrade; //this was missing
}

moving on, the flow of your app.js is important

THE APP

var app = express();
app.enable('trust proxy');
// app.use(cors()); //APP does not need cors because its GENERATING the long lasting session that needs to be read everywhere
//Everything else goes below this
app.use(cookieParser());
app.use(
    session({
        resave: false,
        saveUninitialized: false,
        secret: process.env.SESSION_SECRET,
        cookie: {
            domain: '.domain.com',
            maxAge: 1209600000 // two weeks in milliseconds
        },
        store: new MongoStore({
            mongooseConnection: mongoose.connection,
            autoReconnect: true
        })
    })
);

var mainRouter = require('./routes/main');

THE WEB

var app = express();
app.enable('trust proxy'); 
app.use(cors()); // TO read the cookie being set from elsewhere
var mainRouter = require('./routes/main');

and LASTLY

I had to clear my cookies to remove any false negatives ^ This was the most annoying step


Solution

  • This is possibly due to cookie being set at subdomain level. The session cookie for app.domain.com (app) is not valid for www.domain.com (WEB).

    Try changing code to set cookie at domain level and see if this works.

    app.use(
        session({
            resave: true,
            saveUninitialized: true,
            secret: process.env.SESSION_SECRET,
            cookie: { maxAge: 1209600000, domain:'.domain.com' }, 
            store: new MongoStore({
                mongooseConnection: mongoose.connection,
                autoReconnect: true
            })
        })
    );