0
votes

Good day.

I'm using AWS APIGateway's auto-generated JS SDK in order to perform a PUT request. I have an identity pool, and have therefore enabled IAM auth on the PUT method.

I have a GET request (apigClient.userProfileGet) using the IAM auth working just fine, so I don't suspect it is my policy configuration.

The problem I'm facing is that as soon as I add the body onto the request, I am getting the very vague The request signature we calculated does not match the signature you provided error message.

A sample of my code is as follows:

apigClient = apigClientFactory.newClient({
    accessKey: AWS.config.credentials.accessKeyId,
    secretKey: AWS.config.credentials.secretAccessKey,
    sessionToken: AWS.config.credentials.sessionToken,
    region: 'eu-west-1'
});

let firstName = document.getElementById('firstName_update').value;
let lastName = document.getElementById('lastName_update').value;
let profilePic = document.getElementById('profilePic_update').value;

let body = {
    'firstName': firstName,
    'lastName': lastName,
    'profilePic': profilePic
};

apigClient.userProfilePut({
    'cognito-id-token': session.getIdToken().getJwtToken(),
    'g-id-token': null,
    'fb-access-token': null
}, body).then(data => {
    console.log(data);
});

If I remove the IAM auth, the method executes fine, and I get the response I expect from the backend.

If I leave IAM auth in place, but remove the body, the method executes, and I get the error response I expect from my backend (something like "error, parameters missing in body").

Obviously I need to be able to send the request body..

What am I doing wrong?

Thanks very much

EDIT:

My Request body model looks as follows:

{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "UserDataUpdateRequest",
  "type" : "object",
  "properties" : {
    "firstName": { "type": "string"},
    "lastName": { "type": "string" },
    "profilePic": { "type": "string" }
  },
  "required": [ "firstName", "lastName", "profilePic" ]
}
1

1 Answers

0
votes

So I spent 8 hours trying to figure this out.

The problem was as follows:

This is the Canonical String of the request that was expected by AWS APIGateway:

PUT
/Development/user/profile

accept:*/*
cognito-id-token:eyJraWQiOiIyRFN2VlFNUWZ6c051emxBVWxqRksyd0J4SzdiZ2JiU01SZjlKU1l5NWpzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJjMWY4MWJhZS0xOWZiLTRiYjEtOGI3Ni1kZDE3ZDJjYzVmNjQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5ldS13ZXN0LTEuYW1hem9uYXdzLmNvbVwvZXUtd2VzdC0xX2x0WFNaSGFndiIsInBob25lX251bWJlcl92ZXJpZmllZCI6ZmFsc2UsImNvZ25pdG86dXNlcm5hbWUiOiJsdWtlQHRvdWNoZm91bmRyeS5jby56YSIsImF1ZCI6IjIwczY1bjMyYzJucGM5NmE0MHIxNjM4NmJvIiwidXBkYXRlZF9hdCI6MTQ5NjMyOTQwOTMxNSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE0OTc5NjI3NDksIm5hbWUiOiJMdWtlIiwicGhvbmVfbnVtYmVyIjoiKzI3ODQ4MTcwMDEyIiwiZXhwIjoxNDk3OTY2MzQ5LCJpYXQiOjE0OTc5NjI3NDksImZhbWlseV9uYW1lIjoiSm9obnN0b25lIiwiZW1haWwiOiJsdWtlQHRvdWNoZm91bmRyeS5jby56YSJ9.bXuKyQ-dpU9A4jI-1cViUH_1mV68qObyCREUKwLfzYyBrpNgE_z9YMGpz0uRR7UbgvVMd2LkesXqileZ-H_Gai8M5vqodKQJG2gOOyKPCEvW2G4ieMQgPrkeeWdV77JF4tixdzksJbi4cS78jCgYLgPDp_cn-vOrnkwqSxsu7KUnr3aMoZKvNH7A4mtiJxcLoC-esFdFx1BUzV69NwzX1HOWXk99d3x01Cjes08SBzxTOr3bbEhC0Z0VP0p7sXBL9SSgaecijDIgo9Sa_yKE9amx0Q4jRgf45-NCe2FgRZlpBaouz7blGlt_RUvUACYfgCyBe3LtPDZa3dG5tEhtbg
content-type:application/json
fb-access-token:null
g-id-token:null
host:488s00ffrd.execute-api.eu-west-1.amazonaws.com
x-amz-date:20170620T133151Z

accept;cognito-id-token;content-type;fb-access-token;g-id-token;host;x-amz-date
88e953912796feb4023a4d860ca6e03d62ace022b47a6217865323bf5c7b4b37

And this was the final Canonical String generated by the Javascript SDK that you can generate on APIGateway's site:

PUT
/Development/user/profile

accept:*/*
content-type:application/json
cognito-id-token:eyJraWQiOiIyRFN2VlFNUWZ6c051emxBVWxqRksyd0J4SzdiZ2JiU01SZjlKU1l5NWpzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJjMWY4MWJhZS0xOWZiLTRiYjEtOGI3Ni1kZDE3ZDJjYzVmNjQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5ldS13ZXN0LTEuYW1hem9uYXdzLmNvbVwvZXUtd2VzdC0xX2x0WFNaSGFndiIsInBob25lX251bWJlcl92ZXJpZmllZCI6ZmFsc2UsImNvZ25pdG86dXNlcm5hbWUiOiJsdWtlQHRvdWNoZm91bmRyeS5jby56YSIsImF1ZCI6IjIwczY1bjMyYzJucGM5NmE0MHIxNjM4NmJvIiwidXBkYXRlZF9hdCI6MTQ5NjMyOTQwOTMxNSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE0OTc5NjI3NDksIm5hbWUiOiJMdWtlIiwicGhvbmVfbnVtYmVyIjoiKzI3ODQ4MTcwMDEyIiwiZXhwIjoxNDk3OTY2MzQ5LCJpYXQiOjE0OTc5NjI3NDksImZhbWlseV9uYW1lIjoiSm9obnN0b25lIiwiZW1haWwiOiJsdWtlQHRvdWNoZm91bmRyeS5jby56YSJ9.bXuKyQ-dpU9A4jI-1cViUH_1mV68qObyCREUKwLfzYyBrpNgE_z9YMGpz0uRR7UbgvVMd2LkesXqileZ-H_Gai8M5vqodKQJG2gOOyKPCEvW2G4ieMQgPrkeeWdV77JF4tixdzksJbi4cS78jCgYLgPDp_cn-vOrnkwqSxsu7KUnr3aMoZKvNH7A4mtiJxcLoC-esFdFx1BUzV69NwzX1HOWXk99d3x01Cjes08SBzxTOr3bbEhC0Z0VP0p7sXBL9SSgaecijDIgo9Sa_yKE9amx0Q4jRgf45-NCe2FgRZlpBaouz7blGlt_RUvUACYfgCyBe3LtPDZa3dG5tEhtbg
fb-access-token:null
g-id-token:null
host:488s00ffrd.execute-api.eu-west-1.amazonaws.com
x-amz-date:20170620T133151Z

accept;cognito-id-token;content-type;fb-access-token;g-id-token;host;x-amz-date
88e953912796feb4023a4d860ca6e03d62ace022b47a6217865323bf5c7b4b37

Now play spot the difference!

I'll save you the 8 hours it took me, the SDK was placing content-type underneath my custom header cognito-id-token. Since it's a plain old string comparison, the check was failing.

The solution I renamed my custom headers, all of then. I prefixed x- to them, and now it works.

Damn this was tough to solve .. Hope this saves another poor soul in the future.