Setting up Self Signed SSL on localhost and 192.168.0.*
Lately, I've been experimenting with Service Workers to create a Progressive Web App. One of the requirements of Service Workers is that the host domain has an SSL certificate (or just be on localhost). That's not a problem when I'm working locally on my desktop, but I often test applications on my phone as well. To do that, I setup port forwarding on my network so I can access my localhost server using 192.168.0.* on my phone. That introduces two problems that I've never ran into before...
- Because I'm on my phone, I need the development server to use a self signed certificate that is valid for localhost and 192.168.0.*
- I need to import the self signed certificate onto my Android phone.
To solve #1, I spent the morning digging through stackoverflow and finally found this gem: https://stackoverflow.com/a/41366949/176108
To generate a self-signed certificate that works on localhost, 127.0.0.1, and 192.168.0.100, I ran this command in git bash.
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
-nodes -keyout dev.private.key -out dev.certificate.crt \
-subj "//CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:192.168.0.100"
Which generated dev.private.key
and dev.certificate.crt
.
I then plugged the key and cert into my BrowserSync development server. I added them to the "https" field of the BrowserSync config file.
"https": {
key: "env/dev.private.key",
cert: "env/dev.certificate.crt",
}
After that, I had to import the dev.certificate.crt
file as a trusted certificate in Windows. That was done via Internet Options > Content > Certificates > Import.
Then I copied dev.certificate.crt
to the SD card of my phone. On Android version 9, I then went to Settings -> Security & Location -> Advanced -> Encryption & Credentials and selected "Install from SD Card". I navigated to the folder where I put the .crt
file and then selected it. Android then asked for the name of the certificate and I gave it a name and chose "VPN and Apps" for the "Credential Use" field. I selected OK. Then I went to the "User Credentials" group and saw that the new certificate was added.
I then started my local server and I had a good certificate that worked locally and on my phone and allowed me to use the Service Worker in all locations.
Additional Notes
Along the way, I learned a few details about SSL Certificates and Open SSL.
Subject Alternative Names (SAN)
This line of the command we ran added Subject Alternative Names to the certificate.
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:192.168.0.100"
The SAN list indicates what domain names and IP addresses are secured by the certificate. In the OpenSSL Config file (which I didn't have to use), these are defined in the "alternate_names" section.
[ alternate_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
IP.2 = 192.168.0.105
There are a large number of configuration fields in the OpenSSL Config file. Thankfully, I did not have to set one up.
Remote Browser Inspection
When I was working on this, it was helpful to do some remote debugging. See here for how to do that: https://developer.chrome.com/docs/devtools/remote-debugging
In short, you'll need to enable developer mode on your phone, then go to chrome://inspect/#devices
and find the browser tab that you want to inspect on your phone.