Node.js TypeScript #8. Implementing HTTPS with our own OpenSSL certificate

JavaScript Node.js

This entry is part 8 of 15 in the Node.js TypeScript

HTTPS seems to be everywhere now – it is a great time to go through its principals. In this article we generate our certificate and use the HTTPS module from Node.js. With it, we can implement HTTPS in our local development environment.

What problems does HTTPS solve and how?

To see the advantages, let’s look into some types of attacks that we can prevent with HTTPS. The first one that we talk about is the man in the middle. It is a situation where an attacker inserts himself in-between the client and the server. He can see the traffic, alter it, and relay it to the destination while remaining unnoticed. Imagine sending the password to your banking account when someone is listening! The above is dangerous because, with HTTP, we send the data in plaintext. With HTTPS, it is encrypted. Even if someone eavesdrops on the sensitive data that you submit, he is not able to make much sense out of it – this is especially important if you use a public WiFi network, for example in a hotel or a restaurant. Places like that are great for an attacker to perform the man in the middle attack.

Another issue that can be dealt with to some extent with HTTPS is phishing: obtaining sensitive data like passwords or credit card information by disguising as a trustworthy individual. Imagine receiving an email saying that you need to change your password on Twitter. You visit the provided link and take a look at the top bar with a padlock that says the website uses HTTPS. It does not mean that it is real Twitter though just yet. You can click on it and verify the organization.

Here you can see that for the site to be valid while using HTTPS, it needs a certificate.

Certificates

The certificate can be issued by a certificate authority. You can see it on the screenshot above – the certificate for Twitter is issued by DigiCert. The owner of every website that uses HTTPS has a certificate verifying their ownership of a domain.

While Chrome gets the list of certificate authorities from your operating system, Firefox manages its list. You can get access to it through the application preferences.

If a certificate the website is using isn’t on a list, it is not trusted.

Nowadays HTTPS uses the TLS protocol, the successor of SSL. The details of the connection are not that crucial to us, developers, but we need to know a few essential things about it. During the initial TLS Handshake, the server responds with a certificate. It includes a public key that is later used for encrypting communication during the handshake.

This is an example of assymetric cryptography. It uses a public key that is widely distributed and can be used to encrypt data. To decrypt it you need a private key, that should be kept secret.

The consequence of the above is that to implement HTTPS connection you need a valid certificate and a secret key. Let’s look into ways of getting it.

Generating a certificate and using it

For local development, we can create our certificate without any external certificate authorities. To do it we use OpenSSL that is preinstalled on many Linux distributions. You can also use it on Windows or Mac.

This generates two files for us:   and . The   utility takes a bunch of options, some of them worth mentioning.

  • The first option that we use here is  . It is due to the fact that X509 is the name of the standard of certificates that TLS uses,
  •  option requests a new key. In our case, it uses the RSA algorithm generating a key with the strength of 4096 bits,
  •  argument defines for how long our certificate should be valid,
  •  option means “no DES” and says that we don’t want to encrypt the key itself using the 3DES-CBC algorithm 

Let’s use the files to get the connection started.

Implementing an HTTPS connection in Node.js

To easily implement HTTPS in Node.js we use the https module. It is very similar to the http module that we covered in the previous part of the series.

In the code above, we read both files and pass them to the   function. It allows you to pass additional arguments – you can check the documentation for more on that topic.

Let’s see how the browser reacts to such a response!

The above happens due to the fact that Firefox does not trust us, as the certificate authority. We could change that by expanding its list of certificate authorities. We can ignore that warning when developing locally, but it is crucial to keep in mind, that our certificate is not treated as safe.

Let’s Encrypt

Generating certificates with the method above is good for local development, but you shouldn’t use it if you want to deploy your application. Today it is quite straightforward to acquire your own, free, and valid certificate. An example of a way to do it is to use Let’s Encrypt. They provide a good explanation on how to use it in the docs.

Also, if you are using a web server like Nginx, you might find it more suitable to configure HTTPS through it. You can find instructions in the documentation.

Mixed content

When you serve your website through HTTPS, you need to go all the way. All your files, like CSS and JavaScript, need to be fetched using HTTPS too. That also applies to the API requests. When you attempt to call an HTTP endpoint from an HTTPS site, it fails. Let’s give it a try.

Go to https://reddit.com, open up DevTools and try to make a request to http://jsonplaceholder.typicode.com/posts

As you can see, we got the message about the Mixed Content – this happens when the website loads over an HTTPS connection, but other resources load over an HTTP connection. Browsers block mixed content by default. You can allow it, but it greatly discouraged due to lowered security.

Summary

In this article, we explained the concept of HTTPS. To do it, we covered examples of attacks that we can attempt to neutralize with HTTPS like the man in the middle or phishing. To run HTTPS locally, we generated our own OpenSSL certificate and used it in our application through the HTTPS module. With this knowledge, you can understand HTTPS better and use it locally with your Node.js application.

Series Navigation<< Node.js TypeScript #7. Creating a server and receiving requestsNode.js TypeScript #9. The Event Loop in Node.js >>
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Dmitriy
Dmitriy
4 years ago

You have a typo in
https.createServer({ key, cert }, (req, res) => {
response.statusCode = 200;
response.end('hello world');
})

it must be
res.statusCode = 200;
res.end('hello world');