I've been struggling to send a secure session cookie with express because node isn't recognizing that the request is https. I have an nginx reverse proxy in a docker-compose app. I deploy to Elastic Beanstalk on AWS which handles SSL. I've added logs to check that X-Forwarded-Proto is https in my production environment (at the nginx proxy). But when I log in node
req.headers["x-forwarded-proto"],
req.protocol,
It shows as http http. I am confused on how this setup is supposed to be done.
http {
log_format proxy_debug '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
'"X-Forwarded-Proto: $http_x_forwarded_proto"';
# Set the access log file and apply the custom format
access_log /var/log/nginx/proxy_debug.log proxy_debug;
upstream client {
server client:3000;
}
upstream api {
server api:8080;
}
server {
listen 80;
location /api {
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;
proxy_set_header X-Forwarded-Host $host;
# Use the custom log format
access_log /var/log/nginx/proxy_debug.log proxy_debug;
rewrite /api/(.*) /$1 break;
proxy_pass http://api;
}
location / {
proxy_pass http://client;
# Enable WebSocket support, needed for HMR in React
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
events {}
I've tried setting up a SSL certificate on the reverse proxy itself and using https on my dev environment to debug unsuccessfully.
I see posts like this Configuring HTTPS for Express and Nginx and feel like there should be a simple solution.
In nginx, you are overwriting the X-Forwarded-Proto
header from the load balancer with this line:
proxy_set_header X-Forwarded-Proto $scheme;
The value of X-Forwarded-Proto
might be HTTPS
from the load balancer, but you are then changing it to HTTP
(the value of $scheme
) when you send the request to Express. So from Express's point of view, the request is not secure.
What you need, is to have Nginx simply take the value of X-Forwarded-Proto
that it receives from the load balancer, and pass it on to Express, unchanged.
To do this, you can change that line in your config to the following:
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
Note that the $http_x_forwarded_proto
is available by default in Nginx. You don't need to do anything to declare that variable in your config. This is documented here
$http_
namearbitrary request header field; the last part of a variable name is the field name converted to lower case with dashes replaced by underscores