How to use SSL/TLS with Node.js ?
TLS/SSL is used for establishing secure connections over the internet. Today, most websites use HTTPS to communicate with clients. HTTPS is basically HTTP running over TLS/SSL. Web clients like browsers alert users about websites that do not use HTTPS since such websites are vulnerable to cyber-attacks. As a result, people refrain from visiting such websites. Hence, we must make sure that our web application runs over HTTPS. To set up an HTTPS server, we need an SSL/TLS certificate. This article briefly describes how to use SSL/TLS with Node.js.
We will be building 2 simple express applications that run an HTTP server and an HTTPS server respectively. Import required modules and set up an HTTP server. We create a server.js file and add the following code to it.
server.js
const express = require("express")
const https = require("https")
const http = require("http")
const path = require("path")
const fs = require("fs")
const app = express()
app.get("/", (req, res) => {
res.send("Hello geeks, I am running on http!")
})
const httpServer = http.createServer(app)
httpServer.listen(3000, () => {
console.log("HTTP server up and running on port 3000")
})
Output: After executing the above code, we can head to localhost:3000 to view the application.

The above application is not secure as it runs over plain HTTP. If we click on the symbol to the left of the URL we can see the following.

Generating a self-signed certificate: To generate a self-signed certificate we need the following -
- Private Key
- CSR (Certificate Signing Request)
- TLS/SSL certificate
We will make use of OpenSSL https://www.geeksforgeeks.org/practical-uses-of-openssl-command-in-linux/?ref=gcse for creating the private key and the certificate. Make sure to execute the following commands as administrator.
Step 1: Create the private key.
openssl genrsa -out <location_of_private_key>
openssl genrsa -out D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates\key.pem
This creates a 2048 bit private key using RSA algorithm. -out -> this specifies the location where the generated private key will be stored

-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAmxyRK0ZmY7h9zh6ED+1J5S/UC/mcQlH9daKt0tRPptSrfML4 VcT3TKUXUxv19pgoccm52IjEIbCKUx+5Vi5vL/d2fK0yOvR4v2ZCmj4t6y4cj9KS zzAFYZ8GxHSkXheh5vU/Yv1E4RSV+Ti6lmGy5nzqvV9TevD8pB5Qw8XdC54EI9aX Q5nAVRnCfptZaDXs/af/hc/BhFZnXUf+d4C5BF0cuUI8Qgyb2ePkxeQK0xv0kEsT pzgMw3OKR78N+YY5S6Rx9mECVlJLpNPnxE9+Zd79iyNvj3570x+LV/ckpvdyjrLf njizvWEODleddvx8wElMrdVbfKO+lwt9zb25pwIDAQABAoIBAAOS5u1eU+GcUJm9 LkHHr9ot/e7As477oKFjPCoNZkBryf+35kzjmucTLrRlgodJ/jSQ90076Xj1Plqn 8nc/3qP2Sa6ZtvyQwW93hbVUFW7Dwzi1G1jWvGkBZwCDx327gal2oR1AxKOC++mg Gvx4B80zt5zhY2UDxG5rnGTGXE92LWaUYrM7WuU0NLpbSKk5aibQon2C/dnbZylD RR5VWvUZr3inOyFnPZpuDy6j3Lw2lsB5c8K4LiY/yr5Qu+uO0Tvu8UqeFjur7pI2 Gm2z+muiRsiIZpIFPv+aZ+Ac1RHxTGdrsXRJyVoR/RFzcy2lTmJBYmFfCoqW/2Im ZCY7QTECgYEAzNr6wPKa1N72kGUZOYZPmSVQhI80jYxBbBzZ3ie3SgEKid2VIniz NLtycirj3oh81SfbwWhCwPQqbr7VCtPyiI2lbmURaDJBhEugypAm4FGelnpJtLMQ KYIMOU33tpAhpl5kRi8fBbLDIjvV81lNSuSZOJGPnDqdiraKE7q0OisCgYEAwdZJ 0aJdKRP1brLEaQk4Jl7SAN9MTpyopQOpvQfStXZ/ksz6G1/VrAGt3k/jdS3qO7W1 eDFnwWUqbDdJQHgvh5ZLb85zD4BD8ANMxm8WoC3nJ9xuvCVc2yh83Er60lLJ3w4L UIlWb1ZXikOrQ4e7ZXi3xPp2lqG4jztqToD/bHUCgYEAvgxplZd9DP/MvykLvdJd BjcX++LfXnJAP4yEkxVFdeKBZGWtdc2Ec+dyxXgE7u6w4Q+ZUFTpmRjsRNHF08XN u+GtGD2raH83SQTgpwwVBQazmebZekqlM9zyejdbGIOetDndzT7qCN9PKPNaCelP S6vIejKQiN/YSFgQwTz09wECgYEAhVvKA9miIJ3jsNp7OQynvfZko0b99+PeP1GK 2UvlkwVI9hXiSS0hE6tAFQB/rGH/kj8M7/mFuc/BZRyQYDOP98fWdMDj9pk3pIyQ qMFLHr8WFx2YbgeCoCF17hYEBOoCi1zdOfaTKhyMM8skrFxY+JIaVQJAzpfLI3gs RoCHuvUCgYBqTMK4fvv2KG3x8sHm4rVUyww8P1YDhPK4pXnRYtzkYzlIlDlBvH9M wmOcvWIE5nSa3wUfR5l2YaH8GpO9Ul6bsuN8ot8nsv+rJI/hv1T1pUDC1C/J6X9g bm70rcj82jV6VaAJCV3nwltYhpKr73GbcYHwMM5qcOCmJbTNQ91eqQ== -----END RSA PRIVATE KEY-----
Step 2: Create the CSR
openssl req -new -key <private_key> -out <location_of_csr>
openssl req -new -key D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates \key.pem -out D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates\csr.pem
This command is primarily used for creating and processing certificate signing request (CSR).
-new -> It tells openssl to generate a new CSR.
-key -> It specifies the location of the private key. The private key is required to generate the
corresponding public key.
-out -> It is used to specify the location where the csr will be stored.

The CSR contains vital information that is required by the Certificate Authority as seen in the above image. It also includes the public key of your website/application that will be used to encrypt the data. However, the private key is not a part of the CSR.
-----BEGIN CERTIFICATE REQUEST----- MIICnzCCAYcCAQAwWjELMAkGA1UEBhMCSU4xEzARBgNVBAgMClNvbWUtU3RhdGUx ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKc2Vy dmVyIFRMUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJsckStGZmO4 fc4ehA/tSeUv1Av5nEJR/XWirdLUT6bUq3zC+FXE90ylF1Mb9faYKHHJudiIxCGw ilMfuVYuby/3dnytMjr0eL9mQpo+LesuHI/Sks8wBWGfBsR0pF4Xoeb1P2L9ROEU lfk4upZhsuZ86r1fU3rw/KQeUMPF3QueBCPWl0OZwFUZwn6bWWg17P2n/4XPwYRW Z11H/neAuQRdHLlCPEIMm9nj5MXkCtMb9JBLE6c4DMNzike/DfmGOUukcfZhAlZS S6TT58RPfmXe/Ysjb49+e9Mfi1f3JKb3co6y3544s71hDg5XnXb8fMBJTK3VW3yj vpcLfc29uacCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBgtIW/OVhoCf9/GBAy 7tbLneFPWZJp3jkAk7m2ppPwj8gSm/Otqsx6ajEooixUrPA3xfbQMGPuMeQ37vcL K0AoVRsV3wbXIS3T6YSTmqoLlCioK+PomFA8p1pWvWyb9i+00Ss0M+hBArg18hCf OORXEUrFOJve2huygZO3/fMSifGC7qgTeVr6yx8bbIVzFoky+oikmWXSK9gBTNoM 64sPBNSf33AvK1p64q8yuSPXkZGmdvEjczXEL2diKuNcFHHwv7YLTI1NKKDsWZuu LxY8TNEEFGPf1VZYD3hoGadFk6CvkXlSzskxxtH0sGwgGpAMa+5jnQGbpWYgWzk2 9CLK -----END CERTIFICATE REQUEST-----
Step 3: Create the SSL certificate
openssl x509 -req -days <validity_days> -in <csr_input> -signkey <private_key> -out <location_ssl_certificate>
openssl x509 -req -days 365 -in D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates \csr.pem -signkey D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates\key.pem -out D:\tech_stuff\Gfg_freelance\node_ssl_tls\certificates\cert.pem
x509 specifies the digital certificate standard that is used in the public key infrastructure. It is a multi purpose certificate utility. In this scenario, we are using it to sign a certificate request. -req -> By default this command expects a certificate as an input. With this flag, it expects a certificate signing request as an input. -days -> Specifies the number of days for which the certificate will be valid. -in -> specifies the input file (in this case it is the csr.pem file) -signkey -> This option tells openssl to self sign the input file with the provided private key. (in this case it is the one we created earlier) -out -> specifies the location of the generated certificate.

-----BEGIN CERTIFICATE----- MIIDMDCCAhgCCQDXC8xtR20hBjANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJJ TjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 cyBQdHkgTHRkMRMwEQYDVQQDDApzZXJ2ZXIgVExTMB4XDTIyMTIwMzA5MjAxM1oX DTIzMTIwMzA5MjAxM1owWjELMAkGA1UEBhMCSU4xEzARBgNVBAgMClNvbWUtU3Rh dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwK c2VydmVyIFRMUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJsckStG ZmO4fc4ehA/tSeUv1Av5nEJR/XWirdLUT6bUq3zC+FXE90ylF1Mb9faYKHHJudiI xCGwilMfuVYuby/3dnytMjr0eL9mQpo+LesuHI/Sks8wBWGfBsR0pF4Xoeb1P2L9 ROEUlfk4upZhsuZ86r1fU3rw/KQeUMPF3QueBCPWl0OZwFUZwn6bWWg17P2n/4XP wYRWZ11H/neAuQRdHLlCPEIMm9nj5MXkCtMb9JBLE6c4DMNzike/DfmGOUukcfZh AlZSS6TT58RPfmXe/Ysjb49+e9Mfi1f3JKb3co6y3544s71hDg5XnXb8fMBJTK3V W3yjvpcLfc29uacCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAHLhnk1nlccCbygcI qCmJBv0AHmHlV/sHMQz9hUE2vqb5b6U+UpfCdQjfAletZTsR88U39Ab/peXRyUOj ZlxM/jcRAqYJY4lM32HozSXo4O3LwU3Gc9v7TisajnUgEa1R3sVbT0c7hNr5j1q8 q9nWVB23JYu43dEmbNQbNfhSmHN+j3gXOl8bx20gGwrhobufXvvZkzT6EvbXTHak 0NjDWZ+X2gwUCzDHMUXSwk1SR5FLVzyCXvnqzqVDUmT58vUq7NDdYlBI6HH/zMym rvN3y+OVcTPij24I+MU9kTN2bCAAw5SknoP+G4TZBN0ixFnyZ/J258wDZTUItOKl Xhl1Vw== -----END CERTIFICATE-----
Setting up an HTTPS server: While creating the HTTPS server we have to specify the private key and SSL/TLS certificate in the https.createServer() method. Again in the server.js file, we will add the following code.
const tlsApp = express()
tlsApp.get("/", (req, res) => {
res.send("Hello geeks, I am running on https!")
})
const httpsServer = https.createServer(
{
key: fs.readFileSync(path.join(__dirname,
"certificates", "key.pem")),
cert: fs.readFileSync(path.join(__dirname,
"certificates", "cert.pem")),
},
tlsApp
)
httpsServer.listen(3001, () => {
console.log("HTTPS server up and running on port 3001")
})
Output: We can view the application on localhost:3001.

Although we have used SSL/TLS certificate, the browser still shows Not secure. The reason behind this is the fact that we created a self-signed certificate. Browsers like Google Chrome only trust certificates that are signed by certified certificate authorities like Let's Encrypt, DigiCert, etc.

So, while creating an application that will be deployed in production, we must only use certificates signed by authorized certificate authorities.