« Previous Tutorial Next Tutorial »

Now that our app is production-ready, we want to spend a bit of time making sure it’s as secure as possible. To that end, we’re going to run through some of Express’s best practices for securing your server, and fix a few issues that come up as a result.

Let’s run through some of their suggestions. First up is “don’t use deprecated or vulnerable versions of Express.” This … seems like good advice. Fortunately, we’re using the latest and greatest version of Express, so we should be all set there.

Next up is “Use TLS” – which means running a secure server over HTTPS. This used to be a real pain, and cost money. You can now do it easily and for free, but it requires having a server, which we haven’t gotten to yet. We’ll cover setting up TLS in a couple of tutorials.

“Use Helmet” is their third suggestion, and it’s a good one. Helmet is a collection of middleware functions that adjust your HTTP headers to improve security. It’s super easy to use, so let’s get it installed. First jump into a terminal window or command prompt, cd to your musiclist directory, and type:

yarn add helmet@3.9.0

While that runs, switch to Sublime, open /app.js, and under line 11 add this code:

const helmet = require('helmet');

Then find line 49 and, below it, add this:


That’s all we have to do, so save the file. Next up on Express’s list is “Use cookies securely”. This is, obviously, another good suggestion. To use secure cookies with our session manager, Express-Session, we’re going to need to have TLS enabled on our server. We can make some changes now to app.js to prepare for this, though (and to allow us to continue to work with insecure cookies on our dev server).

First, we’re going to pull our session config out of the require call, so find line 6 and then cut lines 7 to 10, leaving only the semicolon. Also remove the opening paren and brace at the end of line 6. This will give you a line 6 that looks like:

const expressSession = require('express-session');

Now we’re going to work on express session, which is in the big chunk of app.use calls starting on line 40. Normally I'd move this into its own section, but it needs to happen before the passport initialization or our app will break, so just take line 45 and expand it to all of this stuff:

// Express Session
const sessionValues = {
  cookie: {},
  name: 'sessionId',
  resave: false,
  saveUninitialized: true,
  secret: appConfig.expressSession.secret,
if (app.get('env') === 'production') {
  app.set('trust proxy', 1);
  sessionValues.cookie.secure = true;

That should be it, so save the file and let’s move on to the next suggestion, “Ensure your dependencies are secure.” This is a big one … we’re going to use a third party tool called snyk, which will allow us to evaluate our project’s dependencies and list vulnerabilities.

So, switch to a terminal window or command prompt and type the following:

npm install -g snyk

Once that’s run, make sure you’re in your musiclist folder and type

snyk auth

This will open a web browser that’ll allow you to authenticate via Github, Bitbucket, or Google, which is a necessary step to get snyk working for you. Click the authorize button and you should be all set. Head back to your terminal window and type:

snyk test

It’ll run for a while, and then output a whole ton of scary errors, most of them low severity, a few of them high. So, here's the deal … in a real world application, what I'd recommend doing next is running snyk's wizard command, which will try to patch up as many of these issues as it can, and allow you to set 30-day reminders for those that don't have fixes yet. The problem is: generally the solution to fixing vulnerabilities is to upgrade various modules, and that's something we don't want to do for the purposes of this tutorial. In particular, it's going to recommend upgrading both Bootstrap and Express, the former of which is going to introduce minor visual issues, and the latter of which is going to potentially break your web server.

So you have a choice. If you feel confident you can hack away at anything that breaks and get it up and running, then go for it! If you don't want to do all of that, and are just using this as a practice app, then skip running the wizard. In a production app, though, the answer is always "secure as many vulnerabilities as possible, and fix whatever breaks during the securing process."

There are two other things we really should cover in this tutorial. The first is rate-limiting. Rate limiting ensures that someone doesn’t come along and just hammer your API with requests, which can be an effective denial-of-service attack. Let’s make it so that users can only hit our API fifty times per minute. That’s actually a really high rate, but we’re not expecting to have a ton of users, and you could always adjust it based on traffic further down the line.

Still in the terminal window, type the following:

yarn add express-rate-limit@2.9.0

Let that run, then switch to sublime, open app.js, and below line 13 add this code:

const RateLimit = require('express-rate-limit');

Then find line 79, add a padding line below it, and add this code:

// configure rate limiter
const apiLimiter = new RateLimit({
  windowMs: 1 * 60 * 1000, // 1 minute
  max: 50,
  delayMs: 0, // disabled
app.use('/api/', apiLimiter);

This will attach the rate-limiter middleware to any requests sent to our API. Nice. Save this file.

The second thing we need to cover is input sanitization. The last thing you want is someone injecting malicious JavaScript into your site or gaining control of your database via injected commands. Unfortunately there’s no easy single-step solution to sanitizing incoming data. You have to make changes to every API endpoint that receives text from users.

In the spirit of saving some time, I’m going to show you an example of what to do, but leave it up to you to apply the changes across your various endpoints.

First, let’s install a simple string sanitizer. In your terminal window or command prompt, type:

yarn add dompurify@1.0.2 jsdom@11.5.1

When it’s done, head for Sublime and open /routes/api/authentication.js. Below line 1, add this code:

const createDOMPurify = require('dompurify');

Then add the following below line 4:

const { JSDOM } = require('jsdom');

Now head for your register routine on line 53. Below line 61, add the following code:

    // sanitize data
    const window = (new JSDOM('')).window;
    const DOMPurify = createDOMPurify(window);
    const sanitizedBody = {
      username: DOMPurify.sanitize(req.body.username),
      email: DOMPurify.sanitize(req.body.email),
      firstName: DOMPurify.sanitize(req.body.firstName),
      lastName: DOMPurify.sanitize(req.body.lastName),
      password: req.body.password,

Now change lines 73 to 78 to this code:

    const newUser = new User(sanitizedBody);

And line 79 to this:

        return res.send(JSON.stringify({ error: err.message }));

We’re good to go, here. Save the file. Now if a user tries to inject script or other markup into those values, it’ll get eliminated. This does mean that if they happen to put the script tags in their username or email address, they’ll get a slightly confusing “no username” error, but you know what? I’m not real worried about catering to people who’re trying to break my site!

That’s basic sanitation. It’s advisable that you do this for ALL of your API routes, especially if your API is public-facing.

So, that’s about it for securing your app. This is the kind of stuff that becomes increasingly important as your application gains traction and users, to the point that some developers make a very good living just specializing in securing people’s APIs. This tutorial is meant as a starting point only. If you’re trying to deploy a production application, please do a whole lot more research into this area before going live!

In our next tutorial, we’re going to sign up with a host, create a server, and start setting it up. See you then.

« Previous Tutorial Next Tutorial »