It looks like express-session is not setting cookies when working locally or on Safari but they are working fine on Chrome when deployed on Heroku. Never come across this issue before. Below is how I have set up my app.session():
app.use(session({
genid: function(req) {
return genuuid();
},
secret: consts.SECRET_KEY,
resave: false,
saveUninitialized: false,
resave: false
}));
When the user logs in I set req.session.user = aValue and then a resolve on my router checks to see if the server is getting a 200 or 401 back.
Related
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
I've been researching this for hours now. What could be the reason why the cookies are not being saved in the browser? I'm using express-session. Below are the pieces of code I'm using.
const app = express();
// CORS config
app.use(cors({
origin: process.env.API_URL,
credentials: true,
optionsSuccessStatus: 200
}));
app.use(cookieParser());
// Where the sessions are stored
const MongoDBStore = new MongoDBSession({
uri: process.env.MEDIRECORDS_URI,
collection: "sessions"
})
app.set("trust proxy", 1);
const oneDay = 1000 * 60 * 60 * 24;
app.use(session({
name: "irmp_session",
secret: process.env.AWS_SESSION_KEY,
resave: false,
saveUninitialized: false,
maxAge: 7200000, // 2 hrs validity
store: MongoDBStore,
cookie: {
path: '/',
sameSite: false,
secure: false,
maxAge: oneDay
}
}))
When I try to login using the frontend, the login is successful, the session is stored in the database. However, when I check the cookie storage, it is empty.
After spending hours of researching, I learned that this is due to Chrome's cookie updates. Here is what the update is all about.
As the link states, for a cookie to be saved in Chrome and if it is really needed to set the sameSite to none, developers should set the secure option to be true. Default value of sameSite if not set is lax.
Hope this helps anyone who might encounter the problem.
If anyone here uses heroku or render.com for free, I added all the answers above but it is still not working. I have tried another solution here which is add app.set("trust proxy", 1); before app.use(session(sessionSettings)) and it now saves cookie to different browsers.
Thank you so much for sharing it. I was stack on this for 2 days now, in localhost things worked perfectly, but after deploy my MERN app in differents servers, cookie stoped working...
using express-session:
app.use(session({
.......
.......
cookie:{
maxAge: 24*60*60*1000, //please change it based on your needs
secure: app.get('env') === 'production'?true:false,
sameSite: 'none'
}}));
this will solve the problem!!
I'm building a project with authentication. I'm using Node+React. I set an express session cookie on the back-end and I want a component in react to read that cookie to see if the user is authenticated or not. For some reason I can not access that cookie from the react(client-side)... Maybe someone could help out?
BACK:
app.use(session({
name: process.env.SESS_NAME,
resave: false,
saveUninitialized: false,
secret: process.env.SESS_SECRET,
cookie: {
maxAge: parseInt(process.env.SESS_LIFETIME),
sameSite: true, //strict,
secure: process.env.NODE_ENV === "production"
}
}))
FRONT:
import Cookies from "js-cookie";
...
console.log("cookie", Cookies.get("sid"));
I have a cookie named "sid" in this case and I can see it in my console in the browser... but when I try to access it its undefiend
thanks!
Your issue is that you have not set the httpOnly property on the cookie when configuring session. The default value is true which will prevent client browsers from reading the cookie.
Note be careful when setting this to true, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie.
app.use(session({
name: process.env.SESS_NAME,
resave: false,
saveUninitialized: false,
secret: process.env.SESS_SECRET,
cookie: {
maxAge: parseInt(process.env.SESS_LIFETIME),
sameSite: false, // this may need to be false is you are accessing from another React app
httpOnly: false, // this must be false if you want to access the cookie
secure: process.env.NODE_ENV === "production"
}
}))
See the cookie options in docs
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!
I am developing an application in Angular 5 which connects to my server in NodeJS.
I add the user in the req.session object after the user is logged in.
When I make a second request from Angular 5 app to retrieve something from the API, the req.session doesn't contain the user and the req.sessionId is always different.
How can I make the session persistent?
Here are the session and cookieParser middlewares:
app.use(cookieParser(config.secret))
app.use(session({
secret: config.secret,
saveUninitialized: false,
resave: false,
cookie: {
httpOnly: true,
secure: false
}
}))
It was a CORS related issue. I needed to include { withCredentials: true } in the http request options in Angular.