For a WebApp or Backend developers, mixing HTTP & HTTPS while testing a live API from their local environment or the opposite with live webapp connecting to a local backend does usually end with errors such as:
- Mixed Content Warning:
"Mixed Content: The page at 'https://example.com' was loaded over HTTPS, but requested an insecure image 'http://example.com/image.jpg'. This content should also be served over HTTPS."
"Loading mixed (insecure) display content 'http://example.com/image.jpg' on a secure page."
- Blocking of HTTP Requests:
"Mixed Content: The page at 'https://example.com' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com/api'. This request has been blocked; the content must be served over HTTPS."
"Blocked loading mixed active content 'http://example.com/api'."
- CORS Errors:
"Access to XMLHttpRequest at 'http://example.com/api'data from origin 'https://another-example.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://another-example.com' that is not equal to the supplied origin."
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/api. (Reason: CORS header 'Access-Control-Allow-Origin' does not match 'http://another-example.com')"
Web browsers handle HTTP and HTTPS differently and prevent from mixing them for security reasons.
You will find 2 ways to handle this:
- Deactivating security checks
- Generating a self-signed SSL certificate and using local web server
Deactivating security checks
The main reason for not doing so is that you will mix http & https during the development phase and your work will have to be refactored before being published. You may also forget to reactivate security check and use your browser without safetly belt on.
Self-signed SSL certificate
Bellow, you find resources on how you can do it. The drawback is that you need to add a custom root certificate to your system or to your browsers to trust your self-signed one. If you need to simulate the situation with multiple hosts host1.local
, host2.local
you will also need to update your hosts
file to point to 127.0.0.1
- Let's Encrypt provide a well document page on generating Certificates for localhost.
- The Gist from Cecile Muller flow presents how to generate them on your own.
- mkcert simplify making locally-trusted development certificates.
With Let's Encrypt, a domain name and DNS service with an API that allows remote update we can generate wildcard SSL certificate for this domain.
The good news is that when it's done for ones it works for everyone!
Summary of the steps:
- Register a domain name with all
A
entries pointing to127.0.0.1
andAAAA
to::1
- Use let's encrypt to generate a wildcard
*.domain
SSL certificate - Use the certificate in your development stack, from now own you can call
any-name.domain
and it will point out to localhost.
There is a drawback: the validity of wildcard SSL certificates provided by Let's Encrypt are limited to 30 days.
backloop.dev is a domain hosted by Gandi.net a provider which offers an API to update DNS records. Thanks to Github's actions and acme-client a node.js client for Let's Encrypt we can periodically renew the certificate and publish them.
The process is the following:
- A workflow on github is triggered once per week
- The code of backloop.dev - renew is checked out
- The GitHub-pages branch used to publish the certificates is checked-out
renew
process:- Generate a new SSL key and csr (Certificate Signing Request)
- Issues a certificate request to Let's Encrypt
- Receives a DNS "challenge" as a
TXT
record for_acme_challenge
- Update the domain DNS entries with the new challenge on the DNS hosting provider
- Returns to
acme-client
which activates the challenge check - Receives a new certificate
- Posts the new certficate on the Github-pages branch
- Publishes the Github-pages branch
Drop-in certificates: just download them from backloop.dev - you will need to refresh them
Backloop.dev repository contains a node.js folder published on npm with command line tools and integrations with express
, node.js https
and Vue.js
. The tool set will take care of checking and updating the certificates
The following commands require node.js to be installed and backloop.dev
installed globally with
npm install backloop.dev -g
. To avoid installing globally you can also prefix the command with npx
or npx -p backloop.dev
-
Webserver:
backloop.dev <path> [<port>]
Exposes the content of a local directory onhttps://whatever.backloop.dev/
-
Proxy:
backloop.dev-proxy <target host>[:<target port>] [<port>]
Relays
https://whatever.backloop.dev/
=>http://<target host>
-
Download, check and refresh:
backloop.dev-update
To save the certificates in a defined location set the environment varBACKLOOP_DEV_CERTS_DIR
Exemple:
BACKLOOP_DEV_CERTS_DIR=/tmp backloop.dev-update
Integration with Node.js https server:
const https = require('https');
const httpsOptionsAsync = require('backloop.dev').httpsOptionsAsync;
httpsOptionsAsync(function (err, httpsOptions) {
https.createServer(httpsOptions, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8443);
});
More examples and use cases can be found on GitHub repo.
What if *.backloop.dev
DNS A and AAAA entries are not pointing anymore to 127.0.0.1
and ::1
but to another IP (malicious ones)? Then your HTTPS requests will not end-up on your machine, but on this malicious servers.
Even, if this is very unlikely to happend, you may want to be on the safe side by adding <what you need>.backloop.dev
in your /etc/hosts
file.
127.0.0.1 localhost whatever.backloop.dev ...
::1 localhost whatever.backloop.dev ...
You need it for python ? php ? react ? You have a idea of a use case.
Feel free to contribute