API Security using Packages

Securing APIs built with NodeJS, Express, and MongoDB.

Writing a good, strong, secure API takes a lot of time and effort. Luckily, there are some great Packages out there to help with security. By utilizing these you can focus on supporting your application needs while providing security measures by trusted packages.

WHAT’S THE BIG DEAL?

There are a few ways to hack a database (DB), specifically utilizing MongoDB as the DB. MongoDB has as security flaw in regards to usernames and passwords. You can read more about that here.
Other ways to hack a DB include: setting custom security headers, adding scripts to string values that will eventually end up in HTML, spamming the DB with constant requests (DDOS attack), HTTP Parameter Pollution attacks, and bypassing CORS.

PACKAGES TO HELP

To help you focus on your API and know that security is taken care of you should use these packages from NPM:
- express-mongo-sanitize
- helmet
- xss-clean
- express-rate-limit
- hpp
- cors

express-mongo-sanitize

6/6/22, 23,100 weekly downloads

// install
npm i express-mongo-sanitize
// define at the top of your server file
const mongoSanitize = require('express-mongo-sanitize')
// mount in app
app.use(mongoSanitize())

This package handles one “simple” task. Prevent MongoDB Operator Injection. What is that?

Code injection is simply unvalidated data being added (“injected”) into a vulnerable program where it’s executed as application code, often to disastrous results. -Joe Marshall, blog post

For this package that means we’re mainly looking for two things: “$” and “.”
The dollar sign and period are reserved for use by MongoDB as operators.
A simple example could be as follows

{
"username": {"$gt": ""},
"password": {"$gt": ""}
}

This is an issue because the “$gt” has a special meaning in MongoDB as the greater than operator. The comparison is an empty string which means that anything greater than an empty string (any username or password) will return true. This will login/give credentials for the first user listed in the DB, typically an admin.
More information about this particular security flaw can be found here.

helmet

6/6/22, 1,679,096 weekly downloads

// install
npm i helmet
// define at the top of your server file
const helmet = require('helmet')
// mount in app
app.use(helmet())

Helmet is acutally a wrapper for 15 smaller middlewares. This allows us to choose exactly which ones we’d like to use or to just use them all!
This package works by automatically setting various HTTP headers based off the default you mount or by the options you choose.

HTTP Security Headers are necessary to secure your API, site, or application from man-in-the-middle attacks, cookie hijackings, script injects attacks, ClickJacking attacks (related to <frame>, <iframe>, <embed>, and <object> elements), MIME-sniffing vulnerabilities, and only allowing content from defined locations.
Read more about that here.

xss-clean

6/6/22, 15,015 weekly downloads

// install
npm i xss-clean
// define at the top of your server file
const xss = require('xss-clean')
// mount in app
app.use(xss())

This package sanitizes potential malicious user input by cleaning up any possible script tags or other harmful HTML that a hacker could use to attack your DB or site.
Check out the docs for more info.

A quick example would look something like this:
var cleaned = clean('<script></script>')
// will return "&lt;script>&lt;/script>"

express-rate-limit

6/6/22, 365,966 weekly downloads

// install
npm i express-rate-limit
// define at the top of your server file
const rateLimit = require('express-rate-limit')
// define limiter
const limiter = rateLimit({
windowMs: 10 * 60 * 1000, // every 10 minutes
max: 100 // max number of requests in time period defined above
}
// mount in app
app.use(limiter())

The rate limiter is used to limit the amount of times a user can send a request to your API. This is good because we don’t want someone to be able to continuously request data and possibly run up our server bill. This particular package doesn’t just deal with malicious users. However, it will help protect against an attack like a distributed denial-of-service (DDoS) attack. This type of hacking is meant to:

disrupt the normal traffic of a target server, service, or network by overwhelming the target or its surrounding infrastructure with a flood of Internet traffic. -Cloudflare

We use this package as a function that we can then pass our options to. In the example above I’ve only used two options, windowMs (time) and max (amount). This allows me to define the amount of requests I’d like to permit within a defined amount of time. You can also define whether you’d like to add the limit info in the headers and whether you’d like to add a message. Check out the docs to read more and learn about all of the options.

hpp

6/6/22, 40,515 weekly downloads

// install
npm i hpp
// define at the top of your server file
const hpp = require('hpp')
// mount in app
app.use(hpp())

This package add middleware that can protect against HTTP Parameter Pollution attacks.

This evasion technique is based on splitting an attack vector between multiple instances of a parameter with the same name.

This can allow the attacker to bypass pattern based security mechanisms.
- Imperva

An example query might look like:
GET /search?firstname=John&firstname=John
This will result in
req.query.firstname => ['John', 'John']

HPP works by selecting the last parameter value.

cors

6/6/22, 6,743,642 weekly downloads

// install
npm i cors
// define at the top of your server file
const cors = require('cors')
// mount in app
app.use(cors())

CORS issues can plague the developer with problems that take much longer to solve than initially planned. But not without good reason.
Cross-origin resource sharing (CORS) provides a controlled way for sites and apps to share information safely. Same-Origin Policy (SOP) keeps information locked to one origin. This means that having multiple tabs open along with your Banking Site is okay because these different origins won’t be allowed to share information.
Not sharing information is a great security tool, but what if we want to make requests to other origins? This is where we can use CORS.
This package can be used to enable CORS and define what origins we want to allow.

// An example utilizing configurations
var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})

app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})

DOUBLE CHECK SECURITY

While it is very nice to be able to utilize these great packages in your API, it does not replace YOU being responsible for YOUR code and security. Make sure to always double check and test your code to ensure that you are pushing production worthy code that will keep you and your users safe and secure.

Tip or Quote from Brandon:

Today I have a quote!

If you can dream it, you can do it.- Walt Disney

This is the quote I have on a name plate in my office. Seeing this daily reminds me to keep dreaming. The way I see it, the day I stop dreaming is the day I stop doing. I enjoy work, and when I think about it, I always have. Spending hours upon hours everyday “working” is just about the only way I’d have it. The work I do is that of which I enjoy and that which is always taking me somewhere new.
My hard work has taken me across the state for college, across the country for drum corps, to Brazil for music, and halfway across the country for my first teaching job. Now it’s taking me to my home office with my wife where I get to share every day with her.
Keep working, keep dreaming, and keep doing!

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How to stream videos to chrome, firefox, safari

Vue 3 Application Instances

Every web developer should be familiar with these GitHub repositories.

React Native, TypeScript, and React Native Web — an Arduous, but Rewarding Journey

Let’s Build an e-Commerce Web App with Next.js and Go Part 1

Data Fingerprinting in JavaScript

Bootstrap 4 Lit-Element

Bootstrap 4 Lit-Element Lightbase Tutorial

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Brandon Blankenstein

Brandon Blankenstein

More from Medium

How to develop a React and Express application using Vite?

Creating web apps: the tale of a millennial JS developper

5 awesome GitHub Repo for every web developer.

How to add comments in Javascript