How to force node.js/express.js to HTTPS when it is running behind an AWS load balancer How to force node.js/express.js to HTTPS when it is running behind an AWS load balancer express express

How to force node.js/express.js to HTTPS when it is running behind an AWS load balancer


I have experienced the same issue, but in a slightly different context. I was deploying Node.js/Express application using the AWS Elastic Beanstalk and was able to install an SSL certificate on it.

The result of this was that my application was accessible on both the http and https protocol. The routing table of the load balancer were looking like this :

(Load balancer) http 80 --> (Node instance) http 8080(Load balancer) https 443 --> (Node instance) http 8080

So the question was to authorize only https connection on my node.js app, but enabling redirection to https if the connection was done initialy using http.

Because behind the AWS load balancer, all the communication are done over http, a global redirection instruction (as a middleware in this case) like this one would create an infinite redirection loop:

app.use(function(req, res, next) {    if((!req.secure) && (req.protocol !== 'https')) {        res.redirect('https://' + req.get('Host') + req.url);    }}

--> simply becaue the instruction (req.protocol !== 'https') would always be true!

From this blog post (http://matthew.mceachen.us/blog/howto-force-https-with-amazon-elastic-load-balancer-and-apache-1071.html), it turns out that the AWS ELB adds a X-Forwarded-Proto header that you can capture to know what was the protocol used before the load balancer (http or https).

So this small modification did the trick :

app.use(function(req, res, next) {    if((!req.secure) && (req.get('X-Forwarded-Proto') !== 'https')) {        res.redirect('https://' + req.get('Host') + req.url);    }    else        next();});

Hope this help!