A step-by-step guide for getting to https://localhost:3000 Here’s the scenario: You’re a developer, building a web application that will be deployed in production and served up with HTTPS. Meanwhile, as you work on your local machine, you’re testing at . It’s not that big of a deal, but you sure wish you could have . http://localhost:3000 https://localhost:3000 This article will walk you through how to set that up. Step-by-step, we’ll do the following: Create a certificate to make ourselves a Certificate Authority (CA) that can sign SSL certificates. Sign an SSL certificate for . localhost Start up a Node.js Express server that is served up using our SSL certificate. localhost Configure our browser (Chrome, Firefox) and our API client (Postman, Insomnia) to allow for certificates that are signed by ourselves as the Certificate Authority. Visit our local server endpoint with HTTPS, without any certificate security complaints from our browser or API client. Step 1: Generate a CA Certificate The Certificate Authority (CA) is the third-party who signs SSL certificates. They’re the trusted issuers of the Internet, trusted to do their due diligence that you are who you say you are — before they’ll issue you a certificate. Your operating system and your browser has a list of CA’s that they accept as authoritative. If you have a certificate signed by one of these CA’s, then your browser won’t complain. , no CA is going to issue you a certificate for . Why? Because you don’t own . Nobody does. So, the only way to get a CA to sign that certificate is to the CA that signs the certificate. Unfortunately localhost localhost be That’s our first step: generate a root CA certificate. ~$ mkdir cert ~$ cert ~/cert$ mkdir CA ~/cert$ CA ~/cert/CA$ openssl genrsa -out CA.key -des3 2048 ~/cert/CA$ openssl req -x509 -sha256 -new -nodes \ -days 3650 -key CA.key -out CA.pem ~/cert/CA$ tree . ├── CA.key └── CA.pem cd cd # Generate a private key # Choose a simple passphrase for your key. Enter it, re-enter it. # Generate root CA certificate using that key (valid for 10 years) # Enter the passphrase that you chose for the key. # Choose defaults or enter certificate info as appropriate. Step 2: Generate Certificate, Signed By Our CA With CA key and certificate in hand, we can sign SSL certificates as that CA. We’ll need to generate a key and a certificate signing request. Create a new folder, and open a new file in that folder called : localhost.ext ~/cert$ mkdir localhost ~/cert$ localhost ~/cert/localhost$ touch localhost.ext cd This file will contain information that will be written into the signed SSL certificate. localhost.ext authorityKeyIdentifier = keyid,issuer basicConstraints = CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1 We’ll be creating a certificate that works for both and . You can add more domains (for example: ) or IP addresses (for example: ). If you do add more domain names, though, be sure to edit your file to have those domains point to your local machine ( ). localhost 127.0.0.1 DNS.2 = mysite.local IP.2 = 192.168.100.2 /etc/hosts 127.0.0.1 With our certificate settings in place, we generate a key, and then use the key to generate a certificate signing request (CSR): ~/cert/localhost$ openssl genrsa -out localhost.key -des3 2048 ~/cert/localhost$ openssl req -new -key localhost.key \ -out localhost.csr # Generate a private key # Choose a simple passphrase for your key. Enter it, re-enter it. # Generate certificate signing request using key. # Enter the passphrase that you chose for the key. # Choose defaults or enter information as appropriate. # Don't worry about entering anything for "challenge password" Now, with this certificate signing request, we “ask” the CA to sign a certificate for us: ~/cert/localhost$ openssl x509 -req - localhost.csr \ -CA ../CA/CA.pem -CAkey ../CA/CA.key \ -CAcreateserial -days 3650 -sha256 \ -extfile localhost.ext -out localhost.crt # Use the passphrase that you chose for the CA KEY in Step 1. in This command takes in the certificate signing request ( ), the CA certificate and key ( and ), and your certificate extensions file ( ). With those inputs, it generates your certificate file, which is good for 10 years. localhost.csr CA.pem CA.key localhost.ext localhost.crt You get a warning message that says . It’s nothing to worry about. Your certificate will still have been generated. (To get rid of that warning in the future, you can reference .) might unable to write 'random state' this post Our server will need the certificate file, but it will also need the key. We need to decrypt and store that file too: localhost.crt decrypted localhost.key ~/cert/localhost$ openssl rsa - localhost.key \ -out localhost.decrypted.key # Use the passphrase chosen for the localhost key, # which is NOT the same as the CA key. in Step 3: Create an Express Server with SSL Certificate Just to test that this works smoothly, we’re going to create a Node.js Express server that serves up “hello world” at . https://localhost:3000 Up in our folder, initialize a Node.js project, and add the and packages: cert express https ~/cert$ yarn init ... ~/cert$ yarn add express https ~/cert$ touch index.js # Accept all yarn defaults With all our pieces in place, this is what our file looks like: index.js fs = ( ) key = fs.readFileSync( ) cert = fs.readFileSync( ) express = ( ) app = express() app.get( , (req, res, next) => { res.status( ).send( ) }) https = ( ) server = https.createServer({ key, cert }, app) port = server.listen(port, () => { .log( ) }) const require 'fs' const './localhost/localhost.decrypted.key' const './localhost/localhost.crt' const require 'express' const '/' 200 'Hello world!' const require 'https' const const 3000 console `Server is listening on https://localhost: ` ${port} Spin up the server: ~/cert$ node index.js Server is listening on https://localhost:3000 Step 4: Test in Browser and API Client Now that we’re serving up our endpoint with SSL, let’s see what happens in our browser. We’ll use Chrome: Close, but not quite. We’re serving up our endpoint with SSL, and we can even inspect the signed certificate that’s attached. The problem is that Google Chrome that signed this certificate. And rightly so — why should Chrome (and the rest of the world) trust as a CA? does not trust the CA us We’ll deal with this. But first, let’s show what happens in Firefox: And, in Postman: And Insomnia: Everybody complains. But, that’s to be expected. Let’s fix this. Step 5: Import CA Certificate to Browsers In each browser, we need to import our CA certificate to add ourselves as a trusted CA. A quick note on security: You don’t want to go and thoughtlessly add to your list of Certificate Authorities. There are certainly malicious users out there trying to pose as a CA so that they can get you to accept some website (with a certificate signed by that malicious CA) as authentic. For the purposes of this exercise, since we are adding our own CA certificate as a trusted CA, this is a safe operation. In Chrome, open the “Manage Certificates” settings under “Security.” That can be found at . Under “Authorities,” click on the “Import” button: chrome://settings/certificates Choose your file for importing. Click on the box that says “Trust this certificate for identifying websites.” Click on “OK.” ~/cert/CA/CA.pem Now, with our CA trusted, let’s use Chrome to visit our endpoint again: Excellent! In Firefox, it’s a similar process. Open preferences, and navigate to “View Certificates.” From there, go to “Authorities” and click on “Import.” Again, choose the file for importing, checking “Trust this CA to identify websites.” Click on “OK.” CA.pem Now, we test in Firefox: Our browsers are all set up! They trust our CA, and they trust our certificate. Step 6: Configure and Test API Clients In API clients like Postman and Insomnia, the process is similar. However, you could also just , which gets you of the way there. Let’s look at our API clients one at a time. disable certificate validation most Getting mostly there, then all the way there, with Postman In Postman, open up settings and turn “SSL certificate verification” to “OFF.” When we re-send our request in Postman, it looks like this: We’re able to get a , which is pretty good. But we do have that red security warning because we turned off SSL certificate verification. The warning looks like this: 200 OK If we want to get to green, then we can add our CA to Postman, much like we do in our browsers. In Postman settings again, navigate to “Certificates” and then turn “CA Certificates” to “ON.” Select your file as the PEM file. all the way CA.pem Lastly, go back to “General” settings and turn “SSL certificate verification” back to “ON.” We run our request again, and this time we have a secure : 200 OK Insomnia Insomnia also has the option to turn off certificate verification. In “Preferences”, navigate down the general preferences to find and “Validate certificates.” uncheck When we re-run the request in Insomnia, here’s how it looks: It works! At the time of this writing, Insomnia’s desktop client for Ubuntu doesn’t yet have the ability to import your own trusted CA certificates. They’re for Ubuntu/Mac, and they’re too. working on it making progress for Windows Conclusion So, are probably kind of developer. You know, the kind that just to have served up with SSL. Even though you know that the CA, and you signed this SSL certificate , and tweaked your browser and API client settings to accept the certificate. But still, it just warms your heart to see a green lock in your address bar rather than a red warning. you that has localhost you’re yourself you If that’s you, consider yourself equipped. Photo credit (top): by on Rob King Unsplash Photo credit (bottom): Photo by on Clint Patterson Unsplash
Share Your Thoughts