The Serverless Framework logo.

Implementing basic auth with the Serverless Framework

Matt Inamdar Founder
3 Feb 2020

Preamble

We've recently started using the Serverless Framework to host frontend apps (including this website), and we love it!

With it still being a relatively new technology, there are still some nice-to-have features that are lacking, but luckily enough, the framework makes it quite easy to extend and implement them at your desire.

One of the problems we faced was adding basic auth to staging environments. This article will take you through the process of how we got it working.

Prerequisites

This solution is very dependant on the cloud provider being AWS, and so we expect you also to be using them.

You are also expected to have a basic understanding of the Serverless Framework. If you don't, then we recommend you first get yourself up to speed by having a read through their documentation .

An overview of basic auth

In case you don't already know, basic auth is one of the simplest authentication methods you can implement on a website. When you browse to a website that has basic auth, your browser will present a prompt for you to enter a username and password as seen here:

A screenshot of the password prompt shown when basic auth is required

If you enter valid credentials, then your browser caches them and provides them to all further requests to the domain.

How does all this work though?

Good question! Primarily all this is achieved through the use of HTTP headers. Let's look at the flow that takes place:

  1. The browser makes a request to the server.

  2. The server then checks for the Authorization header in the request.

  3. The request header is missing, so the server responds with an HTTP 401 status code, as well as a WWW-Authenticate header letting the browser know that basic auth is required.

  4. The browser will then prompt the user to enter a username and password, as shown in the image above.

  5. The browser will then provide the credentials in all further requests by supplying them in an Authorization header.

The value of the Authorization header is simply the username and password joined with a colon, and then the entire string is base 64 encoded. Finally, the string is prefixed with the word Basic.

If you’re interested in finding out more about how basic auth works, then we recommend reading this article on MDN .

Implementation

Creating a custom authorizer

The Serverless Framework allows us to provide custom authorizers for the API Gateway, which themselves are simply Lambda functions.

This functionality allows us to create a custom authorizer which uses basic auth. You can do this in your project by creating an auth.js file which will contain the Lambda function:

Loading gist...

We won't cover the exact details of what each part of this code is doing, but to summarise:

  1. It gets the Authorization header from the request.

  2. If the header isn't present, it returns a 401.

  3. Otherwise, it then checks the username and password in the header are valid.

  4. If they aren't valid, it returns a 401.

  5. If they are valid, it builds and returns a policy allowing the request through.

The main parts of the code you need to concern yourself with, are lines 14 and 15, which makes references to process.env.AUTH_USERNAME and process.env.AUTH_PASSWORD. This is where the code gets the username and password to validate against. As you can see they are passed into the Lamda function via environment variables. We'll look into how they are passed next.

Configuring Serverless

Now that we have our custom authorizer, it's time to use it on our website. Let's take a look at the serverless.yml file below for the changes you need to make in yours:

Loading gist...

There are a few sections on here which are important to take note of:

Environment variables

On lines 9 and 10, we have specified the username and password to use for the basic auth. We saw above how these environment variables are referenced in our custom authorizer, so this is where we are able to set them.

In order to keep your credentials outside of source control, you would most likely reference these as environment variables from your pipeline: AUTH_USERNAME: ${env:AUTH_USERNAME}.

Specifying the authorizer

On line 32 you can see we have added a new Serverless function for our authorizer. It doesn't have any listeners set up for events, as the function will be referenced from the website function directly.

These references can be seen on lines 19 and 27.

Adding the basic auth header into the response

A single resource has been added on line 37 which is actually merged into the AWS CloudFormation stack that Serverless generates. So it's not adding a new resource, but updating the existing resource which is created for us.

The update to the resource adds a header to the response which requires the browser to use basic auth.

And that's it!

After deploying your Serverless app with these amendments, browse to your website and you should see the basic auth prompt ask you for the username and password.

We have more articles on the way, so be sure to check back regularly! And if you're interested in having a bespoke web app built, then please don't hesitate to get in touch by emailing us at hello@goldspecdigital.com or phoning us on 0113 320 3299 .