HTTP Basic Auth with API Gateway and Serverless

David
4 min readJul 17, 2018

--

Seriously, HTTP Basic Authentication? Are you from the past? Well, the chances of needing it are pretty odd, but if you find yourself in the rare case where you want to protect your Amazon API Gateway endpoints with HTTP Basic Authentication, it’s definitely possible. Here’s how.

How HTTP Basic Authentication works

HTTP Basic Authentication is one of the simplest ways of protecting your API endpoints from the outside world. Do you ever remember you browser opening up a dialog requesting user name and password? That’s basically it:

Example of website prompting for HTTP Basic credentials

This is achieved by relying on the HTTP authentication framework. Its Basic scheme it’s fairly simple, the flow from a browser looks like this:

  1. Someone tries to access a password protected URL

2. The server responds with a 401 HTTP code, and includes the WWW-Authenticate header set to Basic

3. The browser prompts the user for username and password

4. The request is issued again, this time including the Authorization with Basic <token>, being <token> the Base64 representation of username:password

HTTP Basic Auth diagram, taken from Mozilla

How to implement it in Amazon API Gateway

So, we only need to make API Gateway to include the WWW-Authenticate header in 401 responses and check the Authorization header to verify the user’s credentials. We can easily do the former, just by modifying the appropriate Gateway Response. To do so, follow the steps below:

  1. Go to the API Gateway console and select your API
  2. Click on “Gateway Responses” in the sidebar
  3. Select “Unauthorized [401]”
  4. Add a new header, with name WWW-Authenticate and value 'Basic'
Amazon API Gateway 401 with HTTP Basic Auth support

And that’s it, now when our API Gateway doesn’t authorize a visitor to access certain endpoint, she’ll be prompted for credentials. Now we only need our API to check the Authorization header for incoming requests and verify the provided credentials. We can do that by creating a Custom Authorizer, which is basically a Lambda function that API Gateway runs to ensure that the user is authorized to hit an endpoint, before forwarding the request. So, the first step is to create the function. You can find below an example of an authorizer that checks that the provided user name and password are correct:

This authorizer is only intended for demonstration purposes, as you can see, the provided user name and password are compared to hard coded values and the returned policy gives access to the whole API, but you can modify it to fit your needs.

Now we only need to create a Custom Authorizer in API Gateway and hook it up with the endpoints we’d like to protect. To do so, go to the API Gateway console, select your API, click on Authorizers and then on Create New Authorizer. Select your recently created authorizer function and pick Request as Lambda Event Payload. The Identity Source should be the Authorization Header:

We are all set to secure our API with HTTP Basic Authentication, we just need to select the endpoint(s) we want to protect, click on Method Request and select our Custom Authorizer in Authorization:

How to get it working with the Serverless framework

All that sounds good, but it requires quite a lot of manual steps, couldn’t it be automated? Definitely! If you are using the Serverless Framework (which you probably should), this task becomes really simple. Let’s remember what we need:

  1. A Lambda function that holds the authorizer code
  2. Create an API Gateway Custom Authorizer that points to the previous function
  3. Edit the 401 response template to add the needed headers
  4. Hook up the Custom Authorizer with the endpoints

The following serverless.yml file will do the trick:

In the authorizer section we are basically creating the custom authorizer that points to the appropriate function, and protecting our endpoint with it. In the resources section we just modify the 401 response template to match what we need. You can see a sample project with everything set-up here.

--

--