AWS API Gateway to hide request credentials

Motivation

I find very frustrating to setup a server for my website or client app just to make some API calls to various 3rd party services where I only have a private API key (or any credentials I don’t want to make public)

The reason is that you can’t hide anything in your javascript code since it’s visible to anyone. Even if you obfuscate it, people can manage to detect your credentials.

Example: Github Repositories list

We will make an API that list all your repos from github with a simple API Gateway endpoint.

1 — Get a Github access token

First we will check that we indeed need an access token to get our repo list. When calling https://api.github.com/user/repos, you should get the following message:

So let’s create an access token for github: https://github.com/settings/tokens

Click on “Generate new token” button, give a name to your token and check the following boxes:

You should get your github personal token upon validation:

Make sure you copy it in a temporary notepad file or anything else cause you wont see it again afterwards.

This token will let you call our previous endpoint without being rejected, let’s try it by adding “?access_token=YOUR_TOKEN” to our previous url:

So we now have the list of all our repos, included private ones.

2 — Create the API Gateway

Go to your AWS console (or create an account if you don’t already have one): https://aws.amazon.com/

Search for API Gateway from the service search bar:

There click on Create API button and fill the form as below:

3 — Create our API endpoint

Ok, now we have our API, next we will need to add our repos endpoint. In AWS API Gateway an endpoint is defined as a Resource.

From Actions dropdown menu, select Create Resource

Then fill the resource with the following values and save it:

You should get this screen:

So we now have an API with one endpoint/resource: “my-repos” and this endpoint has one method: “OPTIONS”

OPTIONS requests are what we call pre-flight requests used in Cross-origin resource sharing (CORS). It’s a safety mesure done by all major web browsers.

The method we will use to get all our repos will be a “GET” method, so let’s add this one. 
From our Actions dropdown menu, click on Create Method and select the GET one.

Then select HTTP integration type, and fill the endpoint url with our github endpoint including access_token

4 — Test our API Endpoint

You should land on a screen like this:

Notice the Test button in the upper left corner, let’s try our API by clicking on it.

If everything went fine, you should get your repositories list displayed within the response body of your test request on the right part of the screen.

5 — Deploy our API

Good! Now we need to deploy our API to get a public url to reach this endpoint.

From the Action dropdown menu, click on Deploy API

In order to deploy our API, we’ll first need to create a stage for this deployment. See the stage as the environment within which your API is deployed.

Fill it as below and then click Deploy:

Congratz! Your first AWS API is online! :)

Let’s try it in your favorite web browser, and remember to add your resource name at the end of your API root url: https://<root-url>/my-repos

You should see the same result as within your first test with the github url, but now no one can know you access token.

Also since we only add the GET method, the only action anyone could take with this url is only listing your repos (and not any other write/update/delete action that could impact your repos)

6 — Enable API call from javascript

Right know if we try a simple fetch call on our api url from javascript, we will encounter a cross origin problem:

This is because your request response doesn’t included CORS header Access-Control-Allow-Origin. This header tells the browser which domain can access this resource, otherwise you’ll get the red message above.

Let’s go back to our GET method (click it in the left menu) then click on Method Response.

There click on the HTTP Status 200 to expand it, and then click on Add Header button.

We will add only the header name, this will tell the Gateway we want to include this header within our response.

Now that we told the Gateway we want to add this header, we also need to specify our own value for it (and not rely on github for that).

Again let’s head back to the GET method and click on Integration Response. This is where we will map the header with our desired value, in this case it will be and asterisk enclosed by simple quotes: ‘*’

Asterisk is to authorize any domain to request the resource, but you can limit it with only your website domain.

Simple quotes are mandatory, it tells AWS that we want a fixed value (and not a dynamic parameter).

We are almost there! We just need to deploy our API again.

From the Action dropdown menu, click on Deploy API. 
Select the dev deployment stage we’ve created before and hit Deploy. 
Then click on Save Changes button in the bottom right.

If you test again the fetch method within your browser, you should no longer have the CORS error message. This mean you are done and you can use your API within your website/webapp :)

7 — Going Further

In this example we just copy the github url included the access token within the url. But sometimes you’ll need to pass the access_token (or any other auth param) through the request headers.

You can achieve that with header mapping on the Request Integration. It’s quite the same thing we have done with Reponse Integration.

Here is an example:

click on Integration Request

There you can add any number of custom headers with custom values you like:

I encourage you to try various 3rd parties SaaS to transpose this example to the one that really matters to you. But if you can’t manage to make it works don’t give up, I will make a second article which will cover some of the bottlenecks of this example approach.

Limitations

In the previous example you just forward a request and add some context to it. Even if it’s a case i often encounter, you’ll also often want to make some other tasks (form validation for example) before routing the request to a 3rd part service.

You can achieve this with AWS lambda, but we will discuss of that in a later article where we will also see the body mapping which will let you transform the request original body as well as the response body.

Free Tier

Let’s talk money! You don’t want to trade your old cheap server against any services that will cost you an arm or a leg.

The Amazon API Gateway free tier includes one million API calls received per month for up to 12 months.

Afterwards it’s $3.5 per million API calls received, so if you start to pay, it should mean your app is pretty successful, hence it should be affordable ;)

Conclusion

I hope you’ll have a better view of API Gateway and why it can be a great productivity gain if it can avoid you all the standard server setup / admin / configuration and maintainability tasks.

Of course API Gateway is not a silver bullet, you still have some config steps to handle, but on the long run it’s always the maintainability tasks which cost you the most.