White Listing Allowed Origins Dynamically to Secure Your Node Express API via Cors
This article is for anyone who has built an API in Node using Express and is interested in securing it based on the concept of Allowed Origins and CORS or Cross Origin Resource Sharing. You may have secured a good part of your application with token based authorization for an authenticated user or API key, but what about the parts of your application that rely on anonymous or semi-anonymous access? That’s where Allowed Origins come in.
When a consumer sends a request to the API, either through the browser, Postman or a program, the request will include a host in the form of a header or request property. Based on the host, you can allow or disallow access. This prevents bots or malicious actors from abusing your beautiful API. It’s akin to saying “I restrict calls from all phones numbers, except for ones I explicitly know and trust”.
Typically, the Allowed Origins (or phone numbers) you trust are the host address of your front-end and the provided Origin of anyone who signs up for your public API. An example of this is 3rd Party Sign-On with Facebook. When you go to sign up for your login token, it asks you to list all of the locations from which you will call the API.
To achieve the white listing of origins in Node, the easiest solution is to use the CORS package available on NPM. It’s a solidly reliable package that’s easy to use and configure, especially if you have a known list of white listed origins.
The example code provided in the packages readme can be a good starting point, but what if we don’t know the origins ahead of time? We might have to pull them from a database which will be a huge performance issue to look up the origin with every single request..
The star here is node-cache. It will store our origins in memory and provide a fast lookup to compare the origin too. If we were building an enterprise application, we would do the same thing in C# (using the excellent built in AppCache). We could also consider using Redis to store our keys if memory management becomes an issue, but your application would have to grow quite large for that to make sense.
This tutorial assumes a working knowledge of Node. The example code is pretty basic and meant to be adapted to your existing application.
Install needed dependencies.
npm install cors node-cache chalk mongoose shortid crypto-random-string --save
Next, we’re going to setup our ApiKey model for mongoose. Nothing to crazy here.
Bootstrap The Front-End’s Allowed Origin
We have a model, but since the primary consumer is going to be the browser, we want to make sure there is always an allowed origin for our front end. Let’s create a script that we will require at run time. Now if another developer on our team sets up their local environment, they don’t have to worry about creating an origin in the database manually.
Create the Cache
Now we’re into the nitty gritty. The meat of the code if you will. We’re going to dump the database into a cache held in memory. The point of this is to make your list of Allowed Orgins very inexpensive to call in terms of resources. In memory caches offer very fast read and writes.
Create The Middleware Function and Activate It
Now that we have our persisted list of Allowed Origins, we can query it each time we get a request. Based on the Origin header, we can allow or disallow the request.
That’s it. Your API is now secured and only approved callers can access your API. Hit me up on twitter Taylor Ackley if you have any questions.