EdgeAuthorize

Posted by Paul Taylor on September 12, 2019 · 4 mins read

A Lambda@Edge Function for Basic (HTTP401) Authentication

As the world moves back to a more client-side driven way of delivering experiences, so how we can start to address these experiences changes. It hasn’t gone un-noticed that I’m a massive fan of keeping things simple - using the right tools for the job, rather than disappearing into an over-engineered world, only to tick a box to say, “Yup, done that!”.

Amazon Web Services provides an excellent platform for choosing the right components for whatever experience you are trying to deliver - in my case, on my Development & Architecture Blog, I use Amazon CloudFront to distribute content, at the edge, from within an Amazon S3 Bucket Origin - this means that wherever in the world you are, the experience will be delivered locally, due to hundreds of CloudFront “edge” locations.

As you switch from the traditional server-side processing model, into a serverless paradigm (CloudFront and S3), there are a few capabilities that you took for granted that need to be re-architected - one of which is the ability to determine whether a user should be able to access a digital experience or not (think staged content, or perhaps a launch embargo). The easiest way to do this is use HTTP 401 authentication (challenge and response) - while it might not be the most graceful way to prevent un-authorized content to a digital experience, for someone that needs a username- and password-based approach, it will solve the problem just fine.

As an S3 Bucket has no processing capability, we have to re-think the approach slightly. Enter Amazon Lambda, providing the ability to run code, without provisioning servers to do it. Elastically scalable and highly-available, with integration to CloudFront, it provides me with everything that I need to intercept and respond to a request in the right way.

EdgeAuthorize

The reason that I configured EdgeAuthorize is that I had a use-case where I needed to manage the usernames and password within a file that lives in the root of my origin (the S3 Bucket). I need CloudFront to send each request (unless a valid authorization header is present), via my Lambda Function, to the contents in the S3 Bucket, assuming that the correct username and password are supplied.

Luckily there were several useful resources available already for handling HTTP 401 requirements in a Lambda Function (thanks, lmakarov/lambda-basic-auth.js, webscale-oy/aws-cloudfront-basic-auth and Richard Lund) - but they could not read a configuration file from the root of the origin. EdgeAuthorize adds this capability.

EdgeAuthorize is designed for execution upon “Origin Request”, which means, if a CloudFront edge node does not have a locally cached version of the content, for a user presenting the correct authentication header, it will fetch the content and then allow the edge node to cache it for the next user.

EdgeAuthorize Sequence Diagram EdgeAuthorize Sequence Diagram

By deploying this Lambda Function, I have successfully protected my digital experiences from unauthorized access, in a way that allows a successful response to be cached for the next user, at the edge.

EdgeAuthorize HTTP 401 Challenge EdgeAuthorize HTTP 401 Challenge

EdgeAuthorize Authenticated EdgeAuthorize Authenticated

EdgeAuthorize is available under the MIT License at https://github.com/ptylr/Lambda-at-Edge/tree/master/EdgeAuthorize/. If this is going to be useful to you, help yourself!