Force my heroku app to use SSL (https)
Asked Answered
T

12

54

I have a node app running successfully on Heroku. I have purchased an Expedited SSL certificate and it all works fine. I go to https... and get a full 'green bar' proving the site is being served over https

However, the non-SSL standard http is still available too. How can I force the app to serve over https? Thanks

Thornburg answered 18/1, 2016 at 18:57 Comment(0)
P
7

You need to add to the Node.js app the code to redirect the request to the HTTPS version if the request comes from HTTP.

Depending on the framework or the tools you use, the idea is simple:

  • check the request scheme
  • if http, redirect to https passing along the same request uri and query
Pine answered 18/1, 2016 at 19:20 Comment(1)
Official doc entry: can Heroku force an application to use ssl? this article shows you how to implement that redirect at app level using different framework/languagesKitten
H
48

On Heroku, it's slightly tricky to determine the fact that the request came in over http. https is handled at a heroku routing layer and it passes along the request to the node app on http).

This post got me unstuck http://jaketrent.com/post/https-redirect-node-heroku/

Horlacher answered 21/3, 2016 at 19:57 Comment(3)
bro i've been trying to figure this out for 4 months straight, you are god, i owe you my life, thank you.Vilberg
The last code block in that article works really well! But rememeber to put it first of all of express' app.use()Maciemaciel
@HolgerL aww, I wish I saw your reply earlier. Thanks!Leodora
E
31

There's also NPM module heroku-ssl-redirect helping you to deal with it

Excide answered 5/4, 2017 at 9:37 Comment(4)
Worked like a charmFustanella
Still works like a charm in 2019, had this issue with a Create-React-App on Heroku and a domain with GoDaddy. The express server serving the build needed this.Farhi
if you are using nextjs, i created a Middleware version of this package so you don't have to setup a custom server: next-ssl-redirect-middlewareStolen
2022 - doesn't work for me (sslRedirect is not a function)Kokoruda
G
26

I just use the "Always use HTTPS"-Feature from Cloudflare for that. Just follow these steps:

1. Sign Up on Cloudflare if you haven't already

2. Add your site example.com

3. Select a plan. (Free plan is enough for that)

4. Review your DNS records. Cloudflare tries to automatically detect the records if you have already some entries at Namecheap for example. Whats important is that you leave at least the Type A record with the IPv4 address and also the CNAME Type where the Content is the DNS Target from the Domain Name in the Heroku Settings of your App. See also the screenshot

cloudflare_heroku

5. You need to point Cloudflare's nameservers to activate your site successfully otherwise Cloudflare is unable to manage your DNS and optimize your site. Remove existing nameservers and then replace them with Cloudflare's nameservers. They will show you also the instructions on a page (Could take up to 48h until your site is active, but in my experience it took only 15mins). See the screenshot with Namecheap as example:

cloudflare_namecheap

6. Go to the SSL/TLS Section and under the section Edge Certificates enable the "Always Use HTTPS"-Feature. Now all requests with scheme "http" should be redirected to "https"

cloudflare_https

Bonus 1: To forward also requests without the scheme or www for example if the user enters just example.com or www.example.com just create a page rule to forward these requests to your secured url. For that go to the section "Page Rules" and hit the "Create Page Rule"-Button. Enter the url which should match and add the Setting Forwarding URL with the status code 301 - Permanent Redirect. Enter also the destination url as follows with $1 at the end to make it work correctly. Hit "Save and Deploy" and you're ready to go. For more details check the section "Advanced forwarding options" here (Keep in mind that you may need to clear your cache to see the changes). See the screenshot:

cloudflare_page_rule

Bonus 2: You bought another domain and just want to redirect this to your secured main domain. For example you bought fiveexample.com and 5example.com and you want to redirect 5example.com always to https://www.fiveexample.com no matter what the user enters regarding 5example.com e.g. www.5example.com, http://5example.com and even https://www.5example.com even if your second domain has no ssl. Cloudflares page rules are also here a solution. Just follow the steps 1-5 (but at step 4 you don't need the heroku dns target) for your second domain. After you followed the steps to support all forwardings add these three page rules for your second domain. Works also perfectly for .app domains (Keep in mind that you may need to clear your cache to see the changes). See screenshot

redirect_second_domain_to_main_domain

Gauntlet answered 28/9, 2019 at 7:43 Comment(1)
This is the best solutionQuentinquercetin
C
19

For anybody coming along to this post, I was having this problem and discovered that I had code in this order, which was screwing things up:

### old way
app.use(express.static('build'));
app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https') {
    res.redirect(`https://${req.header('host')}${req.url}`)
  } else {
    next();
  }
});

### new way (just swap the order)
app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https') {
    res.redirect(`https://${req.header('host')}${req.url}`)
  } else {
    next();
  }
});
app.use(express.static('build'));

Once I moved the express.static('build') below that send app.use method everything worked!

Cogitative answered 9/3, 2018 at 11:43 Comment(2)
Bro, you are awesome!Oversight
dude youre a life saver <3Stentorian
I
11

If you are developing a creat-react-app and happened to use create-react-app-buildpack to deploy to Heroku (I'm lazy...)

You can specify the following in your static.json file

{
  "https_only": true
}

https://github.com/mars/create-react-app-buildpack#user-content-https-only

Irreligious answered 1/4, 2018 at 7:47 Comment(0)
P
7

You need to add to the Node.js app the code to redirect the request to the HTTPS version if the request comes from HTTP.

Depending on the framework or the tools you use, the idea is simple:

  • check the request scheme
  • if http, redirect to https passing along the same request uri and query
Pine answered 18/1, 2016 at 19:20 Comment(1)
Official doc entry: can Heroku force an application to use ssl? this article shows you how to implement that redirect at app level using different framework/languagesKitten
H
2

You can redirect HTTP requests to HTTPS in the infrastructure layer too, requiring no changes to your application.

The Edge CDN addon offers a "redirect HTTP to HTTPS" option.

It puts the AWS CloudFront CDN in front of your app which is handles the redirect.

The Heroku router doesn't have this feature.

Hardly answered 6/3, 2018 at 15:11 Comment(0)
L
1

As of July 2019, Heroku supports HTTPS redirects to OTHER DOMAINS OR SUBDOMAINS (a redirect cannot point to itself). All you have to do is configure a URL record for your domain as outlined in this post. The full announcement can be found here.

Lox answered 2/8, 2019 at 14:50 Comment(0)
U
1

There are 3 things to note:-

  1. Heroku does NOT have in-built HTTP to HTTPS automatic redirect feature.
  2. Thus, to implement HTTP to HTTPS redirects for your app deployed to Heroku, you will have to include application-level logic instead. Fortunately, Express JS has an inbuilt feature for this. If you are using the node runtime, just mount the following middleware before all routes in the server file:-
 //HTTP to HTTPS automatic redirect
    const requireHTTPS = (req, res, next) => {
      if (!req.secure && req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV !== 'development') {
        return res.redirect('https://' + req.get('host') + req.url);
      }
      next();
    }
    
    app.use(requireHTTPS);
  1. If you don't want to use the above-mentioned application-level logic, then use Cloudflare's Always On HTTPS feature. This is a free feature but requires time to set up as you will have to create a Cloudflare account and use Cloudflare nameservers for your custom domain first.
Unconstitutional answered 8/4, 2023 at 1:17 Comment(0)
S
0

This is how we redirect http to https on Heroku ( we have more than 100 domains pointing to the same site and some are not on SSL hence the domains are also tested in this case. If you don't need that just don't include the domain lines ) :

# Determine if http/https (when behind Heroku proxy it uses X-Forwarded-Proto header to detect)
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ - [env=proto:http]
RewriteCond %{HTTP:X-Forwarded-Proto} =https [OR]
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{HTTP_HOST} ^www\.exampledomain\.com$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www\.otherdomain\.com$ [NC,OR]
RewriteCond %{HTTP_HOST} ^(.*)?.herokuapp.com$ [NC]
RewriteRule ^(.*)$ - [env=proto:https]

There may be room for improvement on this but its been working great for us.

We have a LOT more lines after this block that redirects in other ways so we don't use the L flag at this point.

Storytelling answered 25/9, 2019 at 21:18 Comment(0)
B
0

Using nodejs and express:

const app = express();

app.enable('trust proxy');
app.use(function (req, res, next) {
  if (req.secure) {
    next();
  } else {
    res.redirect('https://' + req.headers.host + req.url);
  }
});
Bivalve answered 9/4, 2021 at 20:7 Comment(0)
L
0

If you're deploying a Laravel project, you can add the following code to 'AppServiceProvider.php' in 'app/Providers/'.

use Illuminate\Support\Facades\URL;

...

public function boot()
{
    if ($this->app->environment('production')) {
        URL::forceScheme('https');
    }
}
Lifeless answered 19/7, 2024 at 15:4 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.