Some will argue we don’t need to use TLS in local development. For some, that may be true. However, I have found in the projects I have been on over the years, that when devs aren’t developing with TLS enabled, odd issues crop up in either in testing (with TLS) or in production that could easily have been caught early. If you are authenticating with an OpenId Connect provider, depending on the provider, your app needs to be using TLS. I personally always use TLS in local development if production will require TLS.
Using TLS in our local development environments means we need a certificate. There are a few ways we can do this. If you are using dotnet like I am, Microsoft has built creating a development cert into the SDK:
dotnet dev-certs https
Or you can create certs using openssl
. This approach is a bit more involved, requires several steps, and manual
deployment of the certs to their appropriate stores.
In the past, I’ve used CertificateTools.com to create dev certs. I like that this site
not only give you the cert(s), but also the openssl
commands and config it used so you can make scripts for your dev
team.
Then I was introduced to mkcert
. It uses openssl
under the hood but not only simplifies the creation of the cert but
also deploys them to the appropriate store. It is my new favorite way to create local dev certs. Let’s take a look.
You can find mkcert on GitHub at https://github.com/FiloSottile/mkcert
Step 1. Install the tool
I use Ubuntu, so to install on my system…
sudo apt install mkcert libnss3-tools
…the GitHub readme has instructions for other operating systems.
Step 2. Install the Certificate Authority
‘mkcert’ uses a certificate authority to sign any dev certs. This makes your local environment more like a real production environment. I’ve run into issues where validating a certificate chain failed in production and wasn’t caught earlier because dev and QA were using self-signed certs.
To install the certificate authority (CA) used to sign our certificates…
mkcert -install
Step 2. Create your certs
Now we are ready to create certs! It couldn’t be easier. Just pass mkcert
the subject name(s) for the certificate you
want to create…
mkcert app.localhost
.localhost TLD
Issues can also be missed in a local dev environment when every deployed component of your application is running on “localhost”, especially around things like CORS and SAME-SITE/SAME-ORIGIN with cookies and iframes.
I used to create dummy DNS entries in my /etc/hosts
file like: db.example.com
, app.example.com
, idp.example.com
so that configuration was more like a production setup and I could ensure things like CORS and cookies are working
correctly.
But no more! In modern operating systems we have the .localhost
top level domain as defined in
RFC 6761.
The .localhost
top level domain (TLD) is supported by Windows, MacOS, and Linux. The local resolver will automatically
resolve any host or host.subdomain
of .localhost
to 127.0.0.1
–the local loopback address without the need to add
entries to your /etc/hosts
file.
Try it for yourself, ping an arbitrary host using that domain. You will see it resolve and successfully ping 127.0.0.1…
ping app.localhost
Putting the two together, you can create certificates for specific apps you are building and get more production-like behavior.
Conclusion
While we don’t always need TLS locally, in some cases, it is beneficial. mkcert
takes the pain away.
Using the .localhost
top-level domain allows us to ensure our app works locally when dealing with things like CORS and
SAME-SITE/SAME-ORIGIN.