connect-mongo cross-domains session issue - node.js

I am having a problem with sessions across sub-domains
I use connect mongo like so:
app.use(session({ // req.session is populated
secret: 'xxxxxx',
saveUninitialized: true,
resave: true,
store: new MongoStore({
db: 'nnn'
}),
cookie: {
path: '/',
maxAge: new Date(Date.now() + time),
domain : 'mydomain.com' ,
httpOnly: true
}
}));
However, when I redirect to a subdomain xyz.mydomian.com the session is invalidated. Can anyone recommend a strategy for getting cross domain login to work with connect-mongo ?

Related

Express doesn't set-cookie when SameSite is none

I have read a lot of other similar questions, but I couldn't solve the issue.
My setup is Node + Express + PassportJs and everything works in development, but I have problems on production.
With the following code, I see that the session cookie is sent back in the response, but I also get a message saying that it won't be applied as SameSite is lax (the default) and the response comes from another site (frontend and backend do not have the same origin).
app.use(
session({
secret: "foo",
resave: false,
saveUninitialized: false,
store: MongoStore.create({ mongoUrl: process.env.MONGO_DB_CONN_STRING! }),
cookie: { httpOnly: true }
})
);
So I changed it to this, so to specify SameSite and Secure in production, but at this point, no cookie is set anymore!
app.use(
session({
secret: "foo",
resave: false,
saveUninitialized: false,
store: MongoStore.create({ mongoUrl: process.env.MONGO_DB_CONN_STRING! }),
cookie: isProduction ? { httpOnly: true, sameSite: "none", secure: true } : {} // <-- only change
})
);
What could be the cause? I've tried to fix it by playing with CORS (no success) and other 100 things. Yet it seems some quirk I am missing.
depending on what service you use to deploy your API(netlify, render.com, heroku other...) you have to enable proxy
this.app.enable('trust proxy');
it fixed my issue

Why can't I set cookies over HTTPS?

I have a server that has its own domain and is using HTTPS. I have a website that has its own domain and is using HTTPS as well.
On the home page of the website, there is a login button and a sign up button. Both buttons lead to forms to execute their respective tasks, and both forms send requests to the server that respond with cookies, or at least that's what they are supposed to do.
I am using express-session in combination with Redis to store the session ids. Here is the config for that (connectToRedis is simply a function that returns a RedisClient):
const RedisStore = connectRedis(session);
const redisClient = await connectToRedis();
app.use(
session({
store: new RedisStore({
client: redisClient,
}),
cookie: {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: TEN_YEARS,
},
resave: false,
saveUninitialized: false,
secret: SECRET,
name: AUTH_COOKIE,
})
);
For some reason the cookies are not being sent in the requests. The Set-Cookie header isn't even showing up! I tried changing SameSite to none (article), but that didn't work.
This is my first time deploying a production website, so all this HTTPS stuff is kind of new to me.
Thanks for your help, and if you need any extra information, please let me know.
IMPORTANT UPDATE:
Finally, I have made some progress (all it took was a pizza break).
I added the path key to my cookie config and gave it the value of /. I also set proxy to true.
So now it looks like this:
const RedisStore = connectRedis(session);
const redisClient = await connectToRedis();
app.use(
session({
store: new RedisStore({
client: redisClient,
}),
cookie: {
httpOnly: true,
secure: true,
sameSite: "none",
maxAge: TEN_YEARS,
path: "/",
},
resave: false,
saveUninitialized: false,
secret: SECRET,
name: AUTH_COOKIE,
proxy: true,
})
);
With this, the cookie is finally appearing in the requests, but it isn't being set in the browser...

express-session Changes the session when the browser is closed

Server on express (4.16.3), with it the express-session (1.15.6) module works.
Code:
// ...
app.use(session({
secret: 'mySecret',
resave: false,
saveUninitialized: true,
store: new MongoDBStore({
uri: 'my-url',
collection: 'sessions'
})
}))
// ...
The essence of the problem: I open the Yandex browser - assign a session, then close it and when I reopen it - a new session. The matter is that authorization is tied to sessions.
The problem is observed in the Yandex browser, microsoft EDGE and in all mobile browsers, while in chrome and opera works correctly.
Help solve the problem or maybe something can replace the module express-sessions
This is happening because your browser default expire the cookie when the browser is closed. In order to fix you can add cookie:{ maxAge: 60000} to your session.
app.use(session({
secret: 'mySecret',
resave: false,
cookie:{ maxAge: 60000},
saveUninitialized: true,
store: new MongoDBStore({
uri: 'my-url',
collection: 'sessions'
})
if you want to make the cookie to not expire, the best way is to set a large number.
// this will it expire in 200 years
cookie: { maxAge: 9000000000000}
or a very far future date in expire property.
// this will expire in year 9999
cookie: {expires: new Date(253402300000000)}

How to configure application to be available subdomain cookie?

I need to share session cookie between main domain and all subdomains. I have two nodejs services based on expressjs framework:
// example.local
...
app.use(session({
cookie: {
domain: "example.local"
}
, key: 'sid'
, secret: '[my secret]'
, saveUninitialized: true
, resave: true
, store: new RedisStore({
host: 'localhost',
port: 6379
})
}));
// blog.example.local
...
app.use(session({
// what should I write here? <---------
}));
So my question is what should I write in session configuration of blog.example.local to get access to existing cookie of example.local?
EDIT: as #yeiniel suggest, I should just use the same config for blog.example.local like the following:
// blog.example.local
...
app.use(session({
cookie: {
domain: "example.local"
}
, key: 'sid'
, secret: '[my secret]'
, saveUninitialized: true
, resave: true
, store: new RedisStore({
host: 'localhost',
port: 6379
})
}));
Is it enough or I may optimize it?
Basically you need two things: Use the same settings on all servers (not just cookie settings but all the session settings included the store) and ensure cookie domain configuration point to the common domain between the sites.
i think your cookie attribute in middleware should be like this,
cookie: {
domain: ".example.local",
path:'/'
}
for blog.example.local and
cookie: {
domain: "example.local",
path:'/'
}
for example.local
Hope this work you.
I am currently managing a similar setup
All apps have the same settings for session
app.use(session({
store: redisStore,
secret: config.secret,
resave: true,
rolling: true,
saveUninitialized: false,
name: config.cookie_name,
cookie: {
domain: config.cookie_domain_name, \\ .website.tld
secure: false
}
You will not be able to use localhost to keep your session data, specially if apps are on different servers. YOu will need a central storage for session data, which all apps can access.

ExpressJS / connect-mongo update session

I'm using connect-mongo to store PassportJS sessions.
My conf in server.js is:
app.use(session({
name: 'Example',
secret:'exampleasd',
saveUninitialized: false,
resave: false,
cookie: { maxAge: 1000*60*60*2 },
store: new MongoStore({
url: 'mongodb://localhost/example',
host: 'localhost',
collection: 'user-sessions',
autoReconnect: true,
clear_interval: 3600
})
}));
My problem is that when I update the users data like the username or email I have to logout and login to get the changes.
I've already tried with req.session.save and req.session.reload, no luck.
Can I update session fields without logout?
Thanks!
You have to use req.user to properly update req.session.passsport.user so:
if you want to change the username just do:
req.user.username = newUsername;
req.session.save(function(err){
//msg here
});

Resources