Forcing HTTPS on Heroku using NodeJS

Hi folks,

I’m just checking in to see if anybody has a good solution that works well with Wappler in order to force our users to be on the HTTPS version of our site?

It’s currently hosted on Heroku with NodeJS using the automated SSL certificates from Heroku.

Is it something done in the routes, or is there something that can be done with express.js, or is there an even better solution? The heroku documentation explains something to do with ensuring that your request headers are set to X-Forwarded-Proto: https, but I don’t quite understand where or how I would do such a thing.

Any advice or solutions would be greatly appreciated!

1 Like

You could try this:

You would apply these changes to the file lib/server.js

Beware Wappler updates could override those

2 Likes

Thank you very much @Apple, I’ll definitely look into this! This certainly looks like it could the solution to my question.

It wouldn’t be a terrible prospect to save the snippet and re-add it if there’s ever a change to that file.

However, I wonder if this could be officially supported by Wappler down the line?

How To Force HTTPS (SSL/TLS) on Heroku (expeditedsecurity.com)

I’m curious if anyone knows of a way to force ssl on Heroku (other than @ Apple’s helpful fix – which is sadly overwritten with each deploy)

Unfortunately the lowest option for this is ~$1,140 USD per per heroku project per year

I know this thread is almost a year old, but I wasn’t able to find a newer answer and am curious how other handle this :slight_smile:

Edit to add: Is there any possibility in using the config technique here to get around the regular re-writes? Thanks all for your help! How to install Sentry on the Back-end (NodeJS) - #21 by patrick

2 Likes

It seems that may be possible, something like this:

var enforce = require('express-sslify');

exports.before = function(app) {
  app.use(enforce.HTTPS());
};

You’ll probably need to npm install express-sslify or something like that too

Hi, I'm trying to force the use of HTTPS on Heroku / Node JS.

I looked at and spoke to expedited security - they have a great WAF solution but a bit overkill / expensive to just force HTTPS. Mike at expedited security suggested using express-force-https - npm. As this doesn't seem to be tied to Heroku wasn't sure how to use/integrate?

I saw this Heroku article that seemed perfect Preparing a Java Web App for Production on Heroku | Heroku Dev Center but as I'm not an expert wasn't sure how and where the Servlet filter code needs to be integrated.

I'm using wappler as im not an expert and the 2 options above are well beyond my capability so would really appreciate others expert guidance on which to use? or another solution and how to integrate this into my wappler app.

Many thanks

Nigel

1 Like

A custom extension is not strictly needed, here's how to do it with pure Wappler:

Create a Server Action with a Set Value step = {{ $_SERVER }}

See which variable changes when you use HTTPS

In your Globals steps add a condition to check such variable and use the Redirect step to redirect to the current URL but with HTTPS

If you get stuck at some step feel free to ask :slight_smile:

1 Like

Thank you so much for your insight and responsiveness.

I'll try and follow your guidance but if stuck may take you up on your offer and may unicast any questions i have.

Regards,

Nigel

Hi, I've got the list of variables and which change depending on if it is HTTP or HTTPS but I'm not sure in what file/folder the check for the http variable exists and how you redirect to the current URL but HTTPS.

I've also read about a solution where you introduce the check and redirection as part of the Servlet filter, I've also read that this is implemented in web.xml file ...but cant find that file/folder or know where the filters are and how you add this additional filter.

Any help would be greatly appreciated.

Thanks,

Nigel
added screenshots of http and https variable settings


any help or guidance would be greatly appreciated.

Thanks

It is idiot that heroku asks money for something like redirecting to https.

Create a new file extensions/server_connect/routes/force_https.js with the following content:

exports.before = function(app) {
  app.use((req, res, next) => {
    if ((req.get('x-forwarded-proto') || '').startsWith('https')) {
      next();
    }

    if (req.method === 'GET' || req.method === 'HEAD') {
      res.redirect(301, 'https://' + req.hostname + req.originalUrl);
    } else {
      res.status(403).send('Please use HTTP when submitting data to this server');
    }
  });
};

This is currently the best solution since it doesn't get overwritten by any future updates. It would be better to have it before any other middleware but there is no extension hook for that.

1 Like

Thank you very much @patrick - this seems to do the job pretty well.

I definitely second your point that it's madness that redirection to HTTPS is a paid feature in this day and age. It's a shame that it has to be done at this layer.

I am going to ask though, are you aware of any way to make the local development web server built into Wappler work when this is added?

My understanding is that the local server doesn't support HTTPS?

Check if the node environment is set to production, if not then skip

exports.before = function(app) {
  app.use((req, res, next) => {
    if (process.env.NODE_ENV !== 'production') {
      next();
    }

    if ((req.get('x-forwarded-proto') || '').startsWith('https')) {
      next();
    }

    if (req.method === 'GET' || req.method === 'HEAD') {
      res.redirect(301, 'https://' + req.hostname + req.originalUrl);
    } else {
      res.status(403).send('Please use HTTP when submitting data to this server');
    }
  });
};

You could consider Cloudflare. The free tier will allow you to redirect all traffic to HTTPS. Relatively simple to set-up and doesn't cost anything at all.

Patrick,
perfect many thanks

Nigel

Hi Patrick,

I now get the following error, any advice or guidance would be greatly received.

ive deleted cookies

Thanks

Nigel

It seems to be in some loop redirecting each time, that means there is something wrong with the detection of the protocol.

It is difficult to tell what goes wrong and will need some debugging.

change

res.redirect(301, 'https://' + req.hostname + req.originalUrl);

into

res.send('https://' + req.hostname + req.originalUrl);

Now it will return the url in the browser and you can check if the generated url it will redirect to is correct.

The same way you could also return req.get('x-forwarded-proto') to check if it indeed contains the value http or https on each request.

great thanks will try these