Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

I'm running a node/express service on AWS and have deployed an ELB in front of it. When I spin up an ELB instance with SSL enabled, it works for the first page I hit, but then switches over to HTTP for every server access after that.

The routing rule on the ELB terminates the SSL and forwards to port 8080 which node is listening on.

The SSL termination solution will work fine for my purposes, but how can I keep subsequent server calls on HTTPS?

like image 707
Greg Avatar asked Jan 26 '12 20:01

Greg


People also ask

Does Express JS support https?

By simply installing the Express NodeJS package and creating a simple configuration script, you can have a secure web service running over HTTPS.

How do I start https Express Server?

Go to the terminal and run the following command. After creation adds key & cert file in your code, and pass the options to the server. const express = require('express'); const https = require('https'); const fs = require('fs'); const port = 3000; var key = fs. readFileSync(__dirname + '/../certs/selfsigned.


1 Answers

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!

like image 79
Kevin. Avatar answered Sep 18 '22 20:09

Kevin.