Request signature does not match in Amazon API

Hi there,

I try to make API call to Amazon using Google Apps Script to get information about Order with ID: XXX-XXXXXX-XXXXXX in marketplace: UK - A1F83G8C2ARO7P.

All the time I get response:

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

I did everything according to the documentation and I used this example:

Using GET with Authentication Information in the Query String (Python) .

For hashing I used library: jsSHA with SHA variant SHA-256.

I think that in formula:

signature = HexEncode(HMAC(derived signing key, string to sign))

I implemented something wrong in second part: string to sign but can’t figure out what exactly.

function amazonGetQuery () {

var date = new Date();
var amz_date = date.toISOString(); //2018-05-01T20:40:50.940Z

var yearMonthDay= Utilities.formatDate(date, ‘UTC’, ‘yyyyMMdd’);
var hourMinuteSec = Utilities.formatDate(date, ‘UTC’, ‘HHmmss’);

var dateForStringToSign = yearMonthDay +‘T’+hourMinuteSec+‘Z’; //20180501T204050Z

var datestamp = yearMonthDay; // 20180501

var access_key = “XXXXXXXXXXXXXXX”;

var method = ‘GET’;
var service = ‘mws’
var host = ‘mws.amazonservices.co.uk’;
var region = ‘eu-west-2’;
var endpoint = ‘https://mws.amazonservices.co.uk/Orders/2013-09-01’;
var canonical_uri = ‘/Orders/2013-09-01’;
var canonical_headers = ‘host:’ + host + ‘\n’;
var signed_headers = ‘host’;

//# Match the algorithm to the hashing algorithm you use, either SHA-1 or
//# SHA-256 (recommended)
var algorithm = ‘AWS4-HMAC-SHA256’;
var credential_scope = datestamp + ‘/’ + region + ‘/’ + service + ‘/’ + ‘aws4_request’;

Logger.log('credential_scope: '+credential_scope);

//# Step 4: Create the canonical query string. In this example, request
//# parameters are in the query string. Query string values must
//# be URL-encoded (space=%20). The parameters must be sorted by name

var canonical_querystring = ‘AWSAccessKeyId=’+encodeURIComponent(‘XXXXXXXXXXXXXX’);
canonical_querystring += ‘&Action=’+encodeURIComponent(‘GetOrder’);
canonical_querystring += ‘&AmazonOrderId.Id.1=’+encodeURIComponent(‘XXX-XXXXXX-XXXXXX’);
canonical_querystring += ‘&MWSAuthToken=’+encodeURIComponent(‘xxx.xxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx’);
canonical_querystring += ‘&MarketplaceId.Id.1=’+encodeURIComponent(‘A1F83G8C2ARO7P’);
canonical_querystring += ‘&SellerId=’+encodeURIComponent(‘XXXXXXXXXXX’);
canonical_querystring += ‘&SignatureMethod=’+encodeURIComponent(‘HmacSHA256’);
canonical_querystring += ‘&SignatureVersion=’+encodeURIComponent(‘2’);
canonical_querystring += ‘&Timestamp=’+encodeURIComponent(amz_date);
canonical_querystring += ‘&Version=’+encodeURIComponent(‘2013-09-01’);
canonical_querystring += ‘&X-Amz-Algorithm=’+encodeURIComponent(‘AWS4-HMAC-SHA256’);
canonical_querystring += ‘&X-Amz-Credential=’+encodeURIComponent(access_key + ‘/’ + credential_scope);
canonical_querystring += ‘&X-Amz-Date=’+encodeURIComponent(amz_date);
canonical_querystring += ‘&X-Amz-Expires=2’;
canonical_querystring += ‘&X-Amz-SignedHeaders=’+encodeURIComponent(signed_headers);

//singing key
var shaObj = new jsSHA(“SHA-256”, “TEXT”);
shaObj.setHMACKey(“41575334XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX456”, “HEX”); //
shaObj.update(datestamp);
var hmac = shaObj.getHMAC(“HEX”);
var shaObj2 = new jsSHA(“SHA-256”, “TEXT”);
shaObj2.setHMACKey(hmac, “HEX”);
shaObj2.update(region);
var hmac2 = shaObj2.getHMAC(“HEX”);

var shaObj3 = new jsSHA(“SHA-256”, “TEXT”);
shaObj3.setHMACKey(hmac2, “HEX”);
shaObj3.update(service);
var hmac3 = shaObj3.getHMAC(“HEX”);

var shaObj4 = new jsSHA(“SHA-256”, “TEXT”);
shaObj4.setHMACKey(hmac3, “HEX”);
shaObj4.update(“aws4_request”);
var signing_key = shaObj4.getHMAC(“HEX”);

//# Step 5: Create payload hash. For GET requests, the payload is an
//# empty string (“”).
//Example hashed payload (empty string)
//e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
var shaObj1 = new jsSHA(“SHA-256”, “TEXT”);
shaObj1.update(‘’);
var payload_hash = shaObj1.getHash(“HEX”);

Logger.log(‘payload_hash: \n’+payload_hash);

//# Step 6: Combine elements to create canonical request
var canonical_request = method + ‘\n’ + canonical_uri + ‘\n’ + canonical_querystring + ‘\n’ + canonical_headers + ‘\n’ + signed_headers + ‘\n’ +payload_hash;

Logger.log(‘cannonical_request: \n’+canonical_request)

//Hashed canonical request
var shaObj7 = new jsSHA(“SHA-256”, “TEXT”);
shaObj7.update(canonical_request);
var hashed_canonical_request = shaObj7.getHash(“HEX”);
Logger.log(‘hashed_canonical_request: \n’+hashed_canonical_request);
//stringTosign
var string_to_sign = algorithm + ‘\n’ + dateForStringToSign + ‘\n’ + credential_scope + ‘\n’ + hashed_canonical_request;
Logger.log(‘string_to_sign: \n’+string_to_sign);

//SIGNATURE
var shaObj5 = new jsSHA(“SHA-256”, “TEXT”);
shaObj5.setHMACKey(signing_key, “HEX”);
shaObj5.update(string_to_sign);
var signature = shaObj5.getHMAC(“HEX”);
Logger.log(‘signature: \n’+signature);

canonical_querystring += ‘&Signature=’ + signature;

var request_url = endpoint + ‘?’ + canonical_querystring;

Logger.log(‘request_url: ‘+request_url+’\n’)

var options = {

  'method' : 'get',
  'muteHttpExceptions':true,
  'host': host,

}

UrlFetchApp.fetch(request_url, options);

}

Result:

credential_scope:

20180501/eu-west-2/mws/aws4_request

cannonical_request:

GET
/Orders/2013-09-01
AWSAccessKeyId=XXXXXXXXXXXX&Action=GetOrder&AmazonOrderId.Id.1=XXX-XXXXXX-XXXXXX&MWSAuthToken=xxxx.xxxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx&MarketplaceId.Id.1=A1F83G8C2ARO7P&SellerId=XXXXXXXXX&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2018-05-01T12%3A02%3A18.889Z&Version=2013-09-01&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXX%2F20180501%2Feu-west-2%2Fmws%2Faws4_request&X-Amz-Date=2018-05-01T12%3A02%3A18.889Z&X-Amz-Expires=2&X-Amz-SignedHeaders=host
host:mws.amazonservices.co.uk

host
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

string_to_sign:

AWS4-HMAC-SHA256
20180501T205153Z
20180501/eu-west-2/mws/aws4_request
XXX436XXXXXXXX3d5beXXXdec39XXXXXXXXXXXXXXXX1d57fb33XXXXXc

request_url:

https://mws.amazonservices.co.uk/Orders/2013-09-01?AWSAccessKeyId=XXXXXXXXXXXXXX&Action=GetOrder&AmazonOrderId.Id.1=xxx-xxxxxx-xxxxxxx&MWSAuthToken=xxxx.xxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx&MarketplaceId.Id.1=A1F83G8C2ARO7P&SellerId=XXXXXXXXXXXXXXXX&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2018-05-01T12%3A02%3A18.889Z&Version=2013-09-01&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXX%2F20180501%2Feu-west-2%2Fmws%2Faws4_request&X-Amz-Date=2018-05-01T12%3A02%3A18.889Z&X-Amz-Expires=2&X-Amz-SignedHeaders=host&Signature=a29XXXXXXXXXXXXXXXXX863b0ade00881XXXXXXXXXXXX1ae1216XXXX

Thanks in advance for any advise in this case.

2 Likes

Amazon has special on-line tool for testing API requests, which calls: Amazon Scratchpad. If you get response through this page without any error then you can compare input data in your code and to find the mistake easily.

Scratchpad URL is different for every market, i.e: for DE it’s Amazon Marketplace Web Services, for UK Amazon Marketplace Web Services etc.

enter image description here

1 Like