Fixing invalid signatures on the AWS API Gateway

Here are some things I learnt the hard way while working with the API Gateway and trying to authenticate users hitting the API. Something by the way that everyone should be doing! Far too many open end-points out there and the APIG (Amazon API Gateway) gives you IAM control or a shared API KEY. This article is focused on getting IAM working: Another post will cover the details of Cognito/IAM and the APIG.

What goes wrong?

To protect my end-points I wanted to use IAM so that the keys used by the end user would expire every 60 minutes and I’d also know exactly who was using the service. I turned on IAM under the authorization of each of my APIG methods. We’ll assume you have valid AccessKey, SecretKey and SessionTokens obtained via the AWS SDK. I started to run into error messages that all looked something like this:

  • Invalid Signature.
  • The request signature we calculated does not match the signature you provided.
  • The Canonical String for this request should have been ….
  • (You’re using a GET request)
  • Any messages related to invalid tokens, sessions etc are tied to issues around how you authenticated and will be covered elsewhere.

The solution

As of this writing I believe this issue lies within the APIG itself. The gateway is making an assumption that when using GET requests that the body is empty and I mean empty! not {}. If you read over the code in the sigV4Client.js you’ll see that an undefined body also gets changed to {}. When the payload signature is calculated against {} it won’t match the server signature which is being calculated against ”. To fix it change your sigV4Client.js – the method buildCanonicalRequest should read as follows:

function buildCanonicalRequest(method, path, queryParams, headers, payload) {
        if (method == 'GET' || method == 'get') payload = '';
        var result = method + '\n' +
            buildCanonicalUri(path) + '\n' +
            buildCanonicalQueryString(queryParams) + '\n' +
            buildCanonicalHeaders(headers) + '\n' +
            buildCanonicalSignedHeaders(headers) + '\n' +
            hexEncode(hash(payload));
            return result;
    }

Although you’re allowed by the HTTP specification to pass data in a GET request you really shouldn’t be :) but the {} as a value is acceptable..

Conclusion

I’ve found it is worth sticking it out with these new technologies as I believe this is the direction backend development is going to take, this along with container services such as Docker will quickly replace the typical VM/Instance model of deployment.

Getting started with the AWS API Gateway

I’m super exited to get started with the brand new service from Amazon Web Services, the API Gateway – AWS API Gateway

The API service is an abstraction to your existing and internal API’s providing not just a front-end service to scale your offerings but also supports automatic generation of SDK’s for using your API! Right out the gate we’ll start by testing our generation of the mobile (iOS) SDK generation to support the expanded SafeChat API v2.

I’ll be focused on SDK support but also scaling and API protection offerings such as, making sure my API end-points aren’t being attacked or flooded.

Stay tuned!