Sharing Redis Sessions Across Node Apps - node.js

I'm busy building a platform with 3 different subdomains - example.com, auth.example.com and api.example.com. They're run with 3 separate NodeJS apps running on different ports of the server.
Here is the code setting up the sessions:
var session = require("express-session");
var redisStore = require("connect-redis")(session);
var redisClient = require("redis").createClient(config.redis);
app.use(session({
secret: config.server.secret,
store: new redisStore(config.redis),
client: redisClient,
resave: false,
saveUninitialized: false,
cookie: {
domain: "example.co.za",
httpOnly: false
}
}));
The configuration is exactly the same for all 3 apps and they're sitting on the same server. For some reason, the sessions are not being shared. I seem to remember that they were being shared a few weeks back and now things are broken - I have a sneaky suspision that this happened when we moved all the traffic from HTTP to HTTPS. Would this break the sessions? I tried to turn of 'httpOnly' in case it restricted the sessions, but no luck.
I have run redid-cli MONITOR and the session is, in fact, being saved on login (Auth App) but is not being retrieved by the other app. When I turned saveUninitialized to true, the requests to save were coming from all 3 apps - this shows that they are connected to the same Redis Store.
Any help would be great.

I think this is just a cookie issue. The browser is not sending the session cookie back on your sub-domains:
you need a leading . on the domain. e.g.:
cookie: {
domain: ".example.co.za",
httpOnly: false
}
In case that doesn't work and you are having AJAX issues see this post

Related

Is Session Port Specific?

I am writing two application on localhost and don't want them to share certain information (Likely on session).
I am wondering if I can open two port? Is the Session storage port specific?
I am wondering if I can open two port?
Yes, you listen on two ports, by starting two servers, one for each port.
Is the Session storage port specific?
Yes and no. It depends upon how the session is configured.
Cookies are not port-specific so by itself a session cookie would be shared between two servers on the same host, but different ports.
So, if you want two instances of express-session on two separate web servers on the same host, but separate ports to use separate sessions, then you can initialize express-session to use separate cookies for each session (by specifying a different cookie name for each) and initialize two separate instances of express-session and then the two sessions will be completely separate.
Here's an example:
const express = require('express');
const session = require('express-session');
// configure first server and session middleware
const app1 = express();
app1.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true },
name: 'session1'
}));
app1.listen(8080);
// configure second server and separate session middleware/session cookie
const app2 = express();
app2.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true },
name: 'session2'
}));
app2.listen(8081);
And, if you're specifying a specific storage medium for the session, then you need to make sure you initialize those to be separate storage locations.

Express-session works wrong when website migrated from http to https?

After we migrated our website from http scheme to https (including enabling https on CDN and redirecting http to https on server), we found that our user sessions works incorrectly sometimes, that is, the user A would be recognized as user B! It seems the session ids of cookies are incorrectly parsed and maybe different users share the same cookies or session ids but all the session ids are generated by uid-safe uniquely.
The issue seems very strange and we really have no idea of the cause.
we use nodejs, Express, express-session with redis storage.
The express-session setup is as below:
app.use(session({
secret: 'xxxx',
cookie: {
maxAge: 3600*24*90*1000
},
store: new redisStore(),
resave: false,
rolling: true,
saveUninitialized: false
}));

express-session secure: true

app.use(session({
secret: "testing credentials",
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie : {
httpOnly: true,
//secure: true,
maxAge : 60 * 60 * 1000
}
}));
I'm working on some security problems on my newly developed website. And after done some research online, if secure=true is set, then it will be more secure. However,
If set secure: true, then information inside session will lose every time when the user send another request. Is there a way to solve this problem? If doesn't include "secure: true" in the cookie: , then the session will last for that maxAge.
If a cookie is set with the secure flag, it will only be sent to the server by the browser over https, and not plain http. This should be the default for production environments.
However, when developing an app, you probably use plain http on your dev machine. If you set your session cookie as secure in this case (using plain http), the server will never receive it, and you will experience a new empty session on each request.
So in short, you should only set the cookie as secure if you are using https (that is, in later stages of your development pipeline, and definitely in production).
On another note, if you set maxAge, the cookie will be persisted, which is not the best practice for session cookies. Without maxAge, the cookie will be kept until the user closes the browser and not normally persisted to disk, which is the correct behaviour for session cookies.

Server to server authentication with Node.js, Passport

I have two services running on different sub-domains: 1) Node.js, Express, PassportJS, 2) PHP based. Both services are exposed in same portal, in order to avoid requiring user to enter credentials twice, we call Node.js login API from PHP server. Node returns session cookie (connect.sid), we forward this to client with domain set to <<rootdomain>>.com. Now when client calls Node.js, we can see cookie being sent to Node but still Node fails to authenticate.
I have verified following things:
Login API call from PHP server to Node returns success with connect.sid cookie and adds session entry into Redis server (We are using Redis for storing sessions)
Cookie is set correctly in browser
When browser calls Node.js connect.sid cookie is sent to server
If we call login API directly from client, everything works as expected. Basically stand alone Node app works without any issues.
I am curious whether Node uses User-agent, IP or something to validate connect.sid cookie? Or is it something related to Passport/Express session params values? What might be wrong? FYI, currently site is not running on SSL.
Here are my session params:
store = new RedisStore({
port: 6379,
host: 'localhost',
client : redis
});
var sess = {
store: store,
secret: 'some secret',
rolling: true,
cookie: { maxAge : 36000000, secure: false },
saveUninitialized: true,
resave: true,
sortName: 0,
sortModified:0,
sortSize: 0
};
Thanks in advance

session persistence between sub domains

I am having two subdomains, api.abc.com and beta.abc.com. Both of them are on same server (box), api.abc.com is running on port 4000 and the beta.abc.com is running on 5000. I am also using node-htty-proxy to reverse proxy the requests. beta.abc.com is used to serve only static content, while api.abc.com returns the response in json.
The user authentication is done through facebook oauth on the server (api) side. Once that is done, session is created and the user is redirected to the beta. The problem I am having here is I am not able to persist sessions! I tried giving the domain option in the cookie obj (as i had seen in other questions), even that din't work.
app.use(express.session({
secret: 'omg'
, store: new mongoStore({
url: config.db.uri
, collection: 'sessions'
})
, cookie: {
domain: ".abc.com"
, maxAge: 1000*60*60*24*30*12
}
}))
How do I go about this? Am I doing anything wrong?
I found a very similar question here.

Resources