skip to Main Content

I intend to HSTS preload a site, and have see the following header. No problem. It works.

Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

A condition of HSTS preloading is that I also redirect all HTTP traffic to HTTPS. To do so, I’m using the following instruction:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

This too, works. If it test my root domain (example.com) at hstspreload.org, I see green and can add my domain to the preload list. This is great, with one caveat.

I want load my site at https://www.example.com, not https://example.com. This should be easy enough:

RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

If it go back to hstspreload.org, I receive the following error:

Response error: No HSTS header is present on the response.

When I enter any subdomain into the hstspreload.org bar, I see green. It’s only on the root domain where I receive the error, because, it seems, the root domain is not sending the HSTS header anymore. However, it’s a condition of preloading that the root domain must send the header.

I did my homework and searched. I read this post from a couple years ago, but my question isn’t about SEO. And, two redirects — one from HTTP to HTTPS and one from to — are okay with Google.

I’m reasonably confident that I can have HSTS preload and WWW redirection. Troyhunt.com redirects to HTTPS and then WWW. The root domain also validates on hstspreload.org. However, I believe he uses IIS, so asking him what do on Apache would help me little.

I’ll be grateful for any ideas. I’m trying, but I’m a bit of a beginner. Thank you!

2

Answers


  1. Chosen as BEST ANSWER

    Got it! All your feedback was spot-on. I never would've gotten this. THANK YOU, Barry!!!

    Here are my working instructions. First, all traffic is redirected to HTTPS. Then, if the connection is HTTPS, the HSTS header gets sent. As you implied, the env=HTTPS wasn't really the right approach. Then, the redirect to WWW happens.

    RewriteEngine On
    
    # Redirect to HTTPS
    RewriteCond %{HTTPS} off
    RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
    <If "%{HTTPS} == 'on'">
     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    </If>
    
    # Redirect to WWW
    RewriteCond %{HTTPS} off [OR,NC]
    RewriteCond %{HTTP_HOST} ^example.com [NC]
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

  2. To include headers on redirects you need to add the always attribute:

    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
    

    I am also not sure when env=HTTPS is set – it might be set after the redirect happens so above will not work?

    To be honest I usually put the HSTS setting in the SSL
    vhost so it only applies to HTTPS connections rather than try to get clever using env=HTTPS.

    If you have several SSL vhosts then this allows you to have different HSTS – for example to not have includeSubDomains on the base domain, but do have it on the www domain. This is useful if you have not yet migrated non-www domains to HTTPS. However for preloading you must have includeSubDomains on both base and www domain so this probably doesn’t apply to you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search