Authentication at Edge with StackPath

As we spread our applications out into serverless micro-services, what better place for our entitlement checks than on the CDN?

Jason Byrne
FloSports Engineering

--

Whether most of the industry realizes it or not, serverless is the future. It is extremely freeing to embrace no longer worrying about managing infrustructure or trying to stay ahead of the traffic curve. Even with auto-scaling it can be a nightmare, and you ultimately pay for more than you need.

The other great thing about the serverless paradigm is that it all but forces you into better coding practices like single responsibility and separation of concerns. You start thinking natively in reusable micro-services and logic becomes infinitely more readable.

However, one thing you can not forget about is securing your content. In our case we have media assets in storage objects (S3 buckets) that are only accessible to authenticated (and paying) users. How can we protect it?

Today we primarily use one of two methods: signed URLs or tokens. Both of these methods work okay, but they create more work than necessary. You need to make at least one round trip to an API that can give you back the URL + signature or hand you a token that gets redeemed. That is before you make the request for the actual content.

Why do we have to go through all this hassle?

When a request hits our API or web server, we already have auth headers baked into the cookies. We use JWT, but you may use something else. What would be more ideal is to have a thin proxy stand between the user and the S3 bucket to do the same thing. No special tokens or signatures needed.

Since we all already use CDNs in front of the raw storage (right??), it would be amazing to have our content delivery network broker that for us. We know that the closer (geographically or network topographically) to the user we can get the faster the request will be. So let’s run code closer to the user also!

There are a growing number of CDN providers that offer the ability to do precisely that: execute code on their edges. You can use it to examine or modify the incoming request or outgoing response. The possibilities this opens up are HUGE.

You will find this capability with AWS Lambda@Edge, Cloudflare Workers, Fastly (via custom VCL), and StackPath EdgeEngine. Three of those products allow you to use JavaScript/Node, which we greatly prefer.

Initially we felt the easy solution was to use Lambda@Edge, since we are already heavy AWS users. They will run your script as part of the CloudFront request-response cycle. However, there are some drawbacks to this.

For one, CloudFront is not the top performing CDN by any stretch. For two, CloudFront is very expensive relative to other CDNs. And for three, there are some weird caveats like you have to deploy your Lambda@Edge code to US-East-1 for some strange reason.

While we’ll continue to use CloudFront for some things, we have been running some proof of concepts with some other CDNs. One of those is StackPath. Thus far we’ve been well-pleased with the price, product offering and insanely great support they have offered.

StackPath just launched their EdgeEngine product in November 2018, as their code-at-edge service. They tout 40Tb/s of network capacity and 45 full-scale PoPs on five continents. The initial CDN setup could not be easier. It walks you through creating the domains, generating a free SSL certs on the fly, and configuring your origin.

From there you can create your first edge script with a few clicks. Their inline editor (with code auto-complete) lets you start playing around with it right away. Clicking save deploys the changes to edge servers worldwide within a couple of seconds, which is pretty remarkable. So it’s very painless to iterate with it in the console and build out a basic proof of concept.

Admittedly, being EdgeEngine is only three months old as I write this, the product is so new that there is a lacking of maturity. Speaking with the StackPath product and engineering team they aim to quickly close these holes. For the time being, I needed to work through these gaps where some of the features, documentation and examples were not yet present.

Firstly… I refuse to develop in JavaScript. I prefer to develop in TypeScript! Call me a snob if you want to, but once you go TypeScript you never willingly go back to vanilla JavaScript. Trust me!

So I created this repository that gets you a template to get up and running with StackPath EdgeEngine and TypeScript:

One of the big things this repository does is transpiles all of your TypeScript code into JavaScript and bundles it up into one file with Webpack. This is a necessary step, for now at least, because you can only deploy a single file to EdgeEngine through the console.

It also includes some basic typings for the StackPath EdgeEngine classes and functions that will make your IDE happy and give you intellisense.

For this basic proof-of-concept, I wanted to parse the cookies from the request and then examine them to determine if the user is authenticated. If they have a valid cookie, let them fetch the file; if not, give them a 403.

The entry point itself couldn’t be much simpler:

For this basic example, we just look for a userId cookie. If it is greater than zero we consider them logged in and they get the file; otherwise, they are rejected with a 403. This is obviously not secure, so you’ll need to update the Auth class to match your authentication method.

Once you make a change simply run this command:

npm run build

This just defers to webpack, which in turn creates the dist/bundle.js file that you can deploy to the EdgeEngine console. You could obviously wire up any other build routines or unit tests you need to add in your build process.

That’s it for now! This is only the beginning in our journey. I hope this helps you get a jumpstart, and you can start to see the great value that we can all realize with edge-side scripts.

--

--