The number of sites switching from HTTP to HTTPS as the default connection protocol has grown drastically in the last few years. It's sufficient to have a look at the Let's Encrypt progress report for June 2016 to get a sense of how fast the web is moving to HTTPS.

The increasing adoption of HTTPS as the default connection protocol for websites has introduced a few new challenges to developers and system administrators. One of them is the need to properly handle redirects to the canonical address of the website to avoid the risk of content duplication. More importantly, configuring the appropriate redirect is necessary to offer a consistent and secure browsing experience.

HTTPS & Redirects

In the past, the most common redirect concern was to properly redirect the www version of the site to the non-www counterpart, or vice-versa. With the introduction of HTTPS, webmasters now also need to take into account the HTTP to HTTPS redirect.

For example, consider the dnsimple.com website: our canonical address is https://dnsimple.com. However, there are 4 common ways an user can connect to our website and we need to make sure we redirect all of them to https://dnsimple.com:

Source Type
http://dnsimple.com HTTP + no-www
https://dnsimple.com HTTPS + no-www
http://www.dnsimple.com HTTP + www
https://www.dnsimple.com HTTPS + www

Configuring these redirects is often a source of confusion. In particular it's not always clear how to properly handle the www-to-non-www (or vice-versa) redirect via HTTPS, and why you need a SSL/TLS certificate for that. In order to properly configure these redirects we need to understand some basic details of how an HTTPS request is processed.

In this article we'll see in which order the HTTPS connection is established, how the HTTP requests are processed, and what are the possible solutions to configure these redirects with HTTPS support. By the end of this post it will also be more clear the reason why our URL redirect service doesn't support HTTPs redirects.

HTTPS request flow

The image above summarizes an HTTPS request/response flow. For simplicity, we grouped the actions in 3 macro phases:

  1. In the first step the client and the server agrees on the encryption details, such as the encryption protocol and the cypher suite. They also exchange the information required to switch to a secure connection, such as the public keys and the certificate information. This phase is called SSL/TLS handshake.
  2. In the second step the client prepares the HTTP request, encrypts it, and sends it to the server for processing. The server receives the encrypted HTTP request, decrypts it, processes the HTTP request, and produces an HTTP response.
  3. In the third step, the server encrypts the HTTP response, and sends it to the client for processing. The client receives the encrypted HTTP response, decrypts, and processes it (for example, a browser will start rendering the response and fetching the assets).

This flow applies to any HTTP request, regardless the content of the HTTP response body or the HTTP response code.

In the previous steps I wrote HTTP request and HTTP response on purpose (notice the use of HTTP and not HTTPS). In terms of content and structure, it's important to understand that an HTTPS request is exactly an HTTP request, but transmitted over a secure (TLS/SSL) connection.

HTTPS negotiation vs Redirect

One of the most common mistakes when configuring an HTTPS redirect is to assume that you don't need an SSL certificate when you redirect from one domain to another domain.

Let's try to understand why this is wrong, and why you need it instead. If you look at the request flow, you will notice that the exchange of the SSL certificate and the encryption negotiation is performed in the first phase. Notice that in this phase the server knows nothing about which page the client wants: the client and server are just deciding how to talk to each other.

Once the first phase is concluded, and both client and server agreed on a common language (the encryption protocol), then they can start to communicate with each other using an encrypted connection. At that point the client will send the HTTP request to the server, and the server in turn will finally respond with the HTTP response containing the redirect.

Don't forget that a redirect is nothing more than an HTTP response with a 301 (sometimes 302 or 307) status code.

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Mon, 01 Aug 2016 14:41:25 GMT
Location: https://dnsimple.com/

Once again, the order is:

  1. The client and the server agree to exchange the SSL certificate information
  2. The client requests the page, with an encrypted connection
  3. The server tells the client that the request resulted in a redirect, with the response sent over an encrypted connection

It should now be clear that even if you want to redirect an entire domain to a different one, you need a valid SSL certificate for the redirecting domain. This is because the encryption negotiation requires the SSL certificate, and the encryption negotiation happens before the request is being processed and the redirect response returned to the customer.

It could not be otherwise: to process the redirect before checking the SSL certificate, the client and the server would be forced to communicate via plain HTTP, making the connection not encrypted, and therefore insecure.

To be even more clear, if you want to redirect any page at https://www.example.com to anything, then you must have a valid SSL certificate installed on the server that covers www.example.com. For instance, to redirect https://www.example.com to https://example.com you need to have a certificate that covers both host names (e.g. a wildcard or a SAN certificate), or two separate certificates, one for each hostname.

Strategies for HTTPS redirects

So far we learned that the HTTP redirect is processed after the SSL/TLS handshake, and that to redirect an entire site or a page under HTTPS you need a valid SSL certificate that covers the domain. In this section I'll show the common strategies to configure an HTTPS redirect.

The two common approaches to redirect with HTTPS are:

  1. Redirect at server level
  2. Redirect at application level

The term server represents any server that is in front of a web application and handles an incoming HTTP request such as a front-end server, a load balancer or a single application server. The term application represents either the web application that can be as simple as a PHP script or more complex as an Unicorn application server interpreting a Ruby on Rails application.

Executing an HTTPS redirect at server level

Performing an HTTPS redirect at server level is generally the preferred option. In this case, the server where the SSL certificate is installed receives the encrypted HTTP request and returns an encrypted HTTP redirect response according to some configuration rules, without contacting the application server or executing the application code.

This approach is generally the fastest one as the server can process the redirect without interacting with the application. However, server configurations are generally less flexible compared to what you can achieve with the power of a full programming language.

Redirects at server levels are generally used for bulk redirects such as redirecting the www to non-www version of a domain with HTTPS (or vice-versa).

The following snippet is a basic example of an Nginx configuration that redirects http://example.com, http://www.example.com and https://www.example.com to https://example.com.

server {
  listen 80;
  server_name example.com www.example.com;
  return 301 https://example.com$request_uri;
}

server {
  listen 443 ssl;
  server_name example.com www.example.com;

  # ssl configuration
  ssl on;
  ssl_certificate /path/to/certificate.crt;
  ssl_certificate_key /path/to/private.key;

  if ($http_host = www.example.com) {
    return 301 https://example.com$request_uri;
  }
}

Although the server level is the preferred option, it's not always feasible as you may not have access to the server configuration. This is the case of shared hosting, or platforms such as Heroku, Azure or Google Platform.

Executing an HTTPS redirect at application level

When you don't have access to the server configuration ,or the redirect logic is a little bit more complex, you need to handle the redirect at the application level.

This approach is a little bit slower than the server level, because the server has to take the request, process the application code (or interact with the application server), and return the response.

The way you perform a redirect at application level depends on the programming language and stack you use. Here are some examples.

Goland and net/http package

You can use http.Redirect.

Ruby on Rails

You can configure the redirect at the router level, use a Rack middleware, or the redirect_to method inside a controller.

constraints(host: /www.example.com/) do
  get '*', to: redirect('https://example.com')
end

PHP

Use the header function to send an HTTP redirect header:

<?php
header('Location: https://example.com/');
exit;
?>

In some cases, this is the only possible approach. For example, if you want to redirect the www to non-www version of a domain with HTTPS on Heroku or Azure (or vice-versa), you will have to point both domains to the same application, install the certificate and conditionally handle the redirect at application level.

Alternative ways to executing an HTTPS redirect

There are a few other alternatives to execute an HTTP redirect, generally applicable for redirecting an entire site to a different domain.

Sometimes you don't have access to the server configuration and the platform where the site is hosted limits your ability to use a programming language. A notable example is Amazon S3 when used to host static sites. In this case, you should explore if the platform provides you some HTTPS redirect feature you can configure. In case of Amazon S3, it's possible to use Amazon Cloudfront to configure an HTTPS redirect.

Another possible approach is to use an standalone, independent redirect application. For example, assuming you want to redirect https://alpha.com to https://beta.com, you can point the DNS for the domain alpha.com to a different service or server where beta.com is hosted, and configure a redirect either at server level or install an application that will just performs as redirector. You will still need a valid certificate for alpha.com installed wherever you are handling the redirect.

Conclusion

With HTTPS becoming the defacto standard for web sites, it is important to configure the appropriate redirects to reduce the content duplication and enforce the use of the HTTPS version of your website.

As you can see, redirecting using HTTPS requires some extra knowledge to make sure the redirecting server is capable of handling incoming HTTPS requests, and send the correct redirect response.

There are many ways to handle URL redirection, and hopefully this post will help you to find the most appropriate for your case.