Learn about security headers by adding them to an Express app in a step-by-step guide.
We're going to cover:
Ingrid Epure: [0:00] For this lesson, we're going to use Visual Studio Code and a browser. The demo project I'm going to use is already opened in VS Code. Let's go ahead and click on app.js to open it as well.
[0:11] The next thing we're going to do is have a look at the request before adding security headers. I like working in the same window. Let's go to View, Terminal and open the terminal window in VS Code.
[0:23] We're then going to run the app using Nodemon. Nodemon takes care of automatically restarting the application every time there's a new change so we don't have to worry about it. My app is running on localhost:3000, which I have loaded here in the browser.
[0:38] We're then going to open Developer Tools by right-clicking and selecting Inspect. We're going to navigate to the Network tab. To be able to see requests, we're first going to have to refresh the page. Our request has now showed up.
[0:50] Let's go ahead and click on it, and navigate to the response header section. You can see that there's not a lot going on here. We have a connection, a content length, and a content type, but not much else. Let's go ahead and add some security headers. Security headers are important because they can prevent vulnerable scripts from running in the app, or do other useful things like instructing the browser to prefer using HTTPS over HTTP so that we always have a secure connection.
[1:18] To add them, we're going to use an npm module called Helmet. Let's go ahead and require that in our application. To make things easier for ourselves, we're also going to assign it to a constant. The next step is telling the app to use Helmet as a middleware, so that the security headers are automatically added for each request.
[1:38] To register Helmet as a middleware, we're going to do app.use(helmet()). We're then going to save at that js and we can see Nodemon already took care of restarting it. Go back to the browser and refresh the page.
[1:52] We're then going to click back on our request and navigate to the response header section. We can now see that some headers have been added. Most notable ones are the Content Security Policy, which prevents malicious scripts from running in the app, and the Strict-Transport-Security header, which instructs the browser to prefer HTTPS over HTTP, so that we have a secure connection.
[2:14] As they are now, the headers have default directives. As the next step, let's look into customizing one of them. For example, the Strict Transport Security has a max-age of 180 days. Let's increase that.
[2:28] The top-level Helmet function we've just added is, in fact, a wrapper to 15 smaller middlewares header, each for its own security header. The one that we want to customize is called hsts.
[2:39] Let's start in the same way with app.use(helmet.hsts()), and then we're going to set max-age to be one year, which for simplicity purposes is approximately 32 followed by seven zeros. We're also going to tell the browser to do the same for subdomains by setting includeSubdomains to true. We're going to save app.js, go back to the browser and refresh the page again.
[3:04] Click back on our request, back to the Response Headers, and if we have a look at the Strict-Transport-Security header now, we can see that the max-age directive has been changed.
Member comments are a way for members to communicate, interact, and ask questions about a lesson.
The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io
Be on-Topic
Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.
Avoid meta-discussion
Code Problems?
Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context
Details and Context
Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!