When not using secure cookie true setting, my app user login works fine. When I enable secure cookies, the login appears to go through fine, but it seems the cookie is not s
My guess is that the actual problem is this:
httpOnly: true
This means that any client-side code cannot access the cookie (through document.cookie
), and any XHR ("AJAX") requests that you perform need to explicitly set withCredentials before any cookies will be sent in the request.
It depends on which client-side setup you're using how to do that:
$.ajax()
That's exactly what secure cookie does. It does not get saved by the browser in an insecure environment, read http://
.
You need to add an ssl sert, redirect all http requests to https and then the cookie would get saved in the browser.
Getting https set up on local is irritating, so set secure
in a config / environment variable you also set to false on your source control and enable it for prod/ staging.
Edit:
Also enable resave, resave: true
Solution if using Heroku:
In Heroku, all requests come into the application as plain http but they have the header X-Forwarded-Proto to know whether the original request was http or https. That causes express to see non-ssl traffic and so it refuses to set a secure cookie when running on Heroku. Express will only send secure cookies over https. You have to tell express to trust the information in the X-Forwarded-Proto header, i.e. that the original request was over https, by enabling the 'trust proxy' setting. Before defining the cookie properties I put
app.set('trust proxy', 1);
Where 1
means trust the first proxy. 1
was good enough for me to set cookie: secure
The combination of settings that worked for me:
proxy_set_header X-Forwarded-Proto $scheme;
Inside the express-session configuration:
server.use(
session({
proxy: true, // NODE_ENV === 'production'
cookie: {
secure: true, // NODE_ENV === 'production'
},
// everything else
})
);
<VirtualHost *:80>
ServerName xx.com
ProxyPreserveHost On
<Location "/">
ProxyPreserveHost On
ProxyPass http://localhost:8080/
ProxyPassReverse http://localhost:8080/
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"
</Location></VirtualHost>
app.set('trust proxy', 1); worked like a charm