Hi, I'm running a react-webpack server at port 8000 and an express js server at port 3000.
While using the express-session at the express server when refreshing the react page causes new session to be generated each time, the session doesn't persist when using it with the react page.
The code I'm using to initiate the session
app.use(session({
secret: 'foo',
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}))
This is an example session generated after a post request of a logging in form.
console.log(req.session)
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false },
meme: 1,
user_name: 'foo',
password: 'bar',
is_logged: 1 }
This is the session after refreshig the page
console.log(req.session)
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false } }
What's causing this error or behaviour?
The same problem is there for the express cookie-session module.
Help is much appreciated.
A few different issues could be causing this. One are you running the app in secure: false and yet accessing the app with https? Two (assuming non-browser) maybe the 'app' isn't returning the cookie? Three multiple instances which are not sharing the session store database and therefore the other instances do not have the session and recreate it?
A few extra details will really also help:
Hopefully you've solved this by now, but it's a common problem to find that cookies don't persist in sessions. See #375, #237, #371, #347, #212, etc.
The big problem in answering this question is we don't know the _context_ of your cookie. Is it behind nginx? Are you using https? These are important questions, and Express.js can't answer them all by itself.
If behind nginx, make sure you've set the proxy headers correctly on nginx's part. Here's my proxy route. Look up a nginx reverse proxy guide to set this up.
location @node {
proxy_redirect off;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
For me, the line that fixed cookie persistence is proxy_set_header X-Forwarded-Proto $scheme;
If using https, the Express app has to trust the proxy, and then configure itself for secure cookies.
app.set('trust proxy', true)
// The documentation specifies '1' instead of 'true'
app.use(session({
store: new RedisStore({
pass: 'asdf',
}),
secret: 'asdf',
proxy: true,
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
And, of course, make sure nginx is running on https. Node can run on good ol' HTTP.
I don't have any documentation for http; it should be the regular. _Maybe_ explicitly set cookie: { secure: false }
If using cookieParser, make sure you've fed the secret into cookieParser in place of the secret into session. I think. There's another issue on that.
@dougwilson we might want to add something about the nginx proxy_set_header X-Forwarded-Proto $scheme; (maybe even a whole example setup for https) and or a note about the X-Forwarded-Proto in general for other reverse proxies (since in recent months/years many have been popping up). I bet most of those issue are related. I had forgotten about the X-Forwarded-Proto since I just borrow Cloudflare's headers which already correctly include that my nginx behind it doesn't need that header. I think having a mention of the X-Forwarded-Proto within the cookie.secure area might be beneficial.
@gabeio https://github.com/expressjs/session/issues/281#issuecomment-200329301
@au for the time being I'm using a temporary solution and moving on hoping to come back to the session issue later. The express server is running on my laptop without any Nginx or https. I will look into the threads you have given in your answer. Meanwhile the problem is persisting.
Actually when I am requesting a route by typing the expressjs route to the browser in a dummy route the sessions are persisting, the issue occurs when run together with webpack server. My guess is the problem is something to do with that.
Interesting! I'd look over the documentation on how webpack stores cookies and encrypts them.
@rukshn I ran into the same issue with Angular2 running on webpack-dev-server. Turns out that the cookies weren't being sent to my custom node/express server (log the req.headers object and see if you see cookies being set there). You might want to check with the react doc, but Angular2 has the flag withCredentials: true. I also had to configure options for the cors module on the node side.
var corsOptions = {
origin: 'http://localhost:3000', // webpack dev server port
credentials:true
}
Hope this helps!
Same problem... I am using webpack + react
How to add cookie on webpack.config.js under proxy? When I logged in, the public host server, provides a cookie and append at the http header. When the webpack-dev-server detect an api path from the url, I don't see the set-cookie being added, probably I missed some config from the proxy?
e.g.
devServer: {
proxy: {
"/api": {
target: "http://publicdomain:3000",
changeOrigin: true,
secure: false
},
I found my problem... I am using fetch for my frontend calls and fetch does not re-use cookies by default (I am spoiled by jQuery). I wasn't using credentials: "same-origin", thus a new session was being created for each request on the frontend.
Reference: https://davidwalsh.name/fetch#comment-503923
My code looks like this - hope it helps someone:
fetch(url, {
method: 'GET',
credentials: 'same-origin',
})
.then(function(response){
return response.json();
})
.then(function(json) {
console.log(json);
});
@tatemz Have you run into an issue where on some devices a new session is still being created?
@DanielLuu - Haven't seen any yet. Once I fixed my fetch calls, I haven't seen any issues with my sessions.
when I use
fetch(url, {
method: 'GET',
credentials: 'same-origin',
})
most of the request will not create sessions,
But when I refresh my page, it still create new empty sessions.How could I solve it?
I use fetch+react+react-router
For my case when testing, I need to use
fetch(url, {
credentials: "include",
}
since webpack-dev-server on port 8080 and API testing server on another port.
Sorry I've left this issue open, but recently was able to determine in another issue that the answer from @liukun seems to be the right answer for how Webpack is setting up the server + front end on the different ports.
+1 for @liukun solution, fixed the issue for me, and I'm using React + Webpack + Apollo Client + Express Graphql behind Nginx proxy
@tatemz you're a Saint. Work for me.
@brendonco 's answer was the one for me. I was using Vue/Webpack dev server and a node express backend and a proxy in the webpack dev server to the backend preserved the sessions.
Thank you @liukun . Adding credentials: include to my fetch request solved the issue.
Although I got a cors error at first. I had my cors set to a wildcard (meaning requests from all other origins are allowed), but to accept credentials with cors it is necessary to specify the origin of the request.
I'm using the cors package for node.js and changed my cors options to this to make it work:
const corsOptions = {
origin: http://localhost:3000, //the port my react app is running on.
credentials: true,
};
app.use(cors(corsOptions));
How to add cookie on webpack.config.js under proxy? When I logged in, the public host server, provides a cookie and append at the http header. When the webpack-dev-server detect an api path from the url, I don't see the set-cookie being added, probably I missed some config from the proxy?
e.g.
devServer: { proxy: { "/api": { target: "http://publicdomain:3000", changeOrigin: true, secure: false },
thanks alot
Most helpful comment
I found my problem... I am using
fetchfor my frontend calls and fetch does not re-use cookies by default (I am spoiled by jQuery). I wasn't usingcredentials: "same-origin", thus a new session was being created for each request on the frontend.Reference: https://davidwalsh.name/fetch#comment-503923
My code looks like this - hope it helps someone: