I was trying to write a code in Js for GET request via REST API. I am trying to generate signature using the shared key and access key provided by me
var https = require('https');
var crypto = require('crypto');
function sign(key, message) {
return crypto.createHmac('sha256', key).update(message).digest();
}
function getSignatureKey(key, dateStamp, regionName, serviceName) {
kDate = sign('AWS4' + key, dateStamp);
kRegion = sign(kDate, regionName);
kService = sign(kRegion, serviceName);
kSigning = sign(kService, 'aws4_request');
return kSigning;
}
// values retrieved from Cognito Federation
accessKey = "MYACCESSKEY";
secretKey = "my/sharedkey";
region = "us-east-1";
serviceName = "s3";
// ex 20180518T210317Z
var now = new Date();
amzdate = now.toJSON().replace(/[-:]/g, "").replace(/\.[0-9]*/, "");
datestamp = now.toJSON().replace(/-/g, "").replace(/T.*/, "");
// prepare to send an HTTP request to https://your-api-gateway.execute-api.eu-west-2.amazonaws.com/stage/secure/endpoint
apiMethod = "GET";
apiHost = "my_host_name.com";
apiEndpoint="/bucket_name/object_name";
apiQueryString = "";
canonicalHeaders = "host:" + apiHost + "\nx-amz-date:" + amzdate +"\n";
//"\nx-amz-security-token:" + sessionToken + "\n"
signedHeaders = "host;x-amz-date;";
payloadHash = crypto.createHash('sha256').update('').digest('hex');
canonicalRequest = apiMethod + "\n" + apiEndpoint + "\n" + apiQueryString +
"\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + payloadHash;
console.log('preparing to invoke canonical request:');
console.log(canonicalRequest);
// ************* TASK 2: CREATE THE STRING TO SIGN*************
// Match the algorithm to the hashing algorithm you use, either SHA-1 or
// SHA-256 (recommended)
algorithm = 'AWS4-HMAC-SHA256';
credentialScope = datestamp + '/' + region + '/' + serviceName + '/' +
'aws4_request';
stringToSign = algorithm + '\n' + amzdate + '\n' + credentialScope + '\n' +
crypto.createHash('sha256').update(canonicalRequest).digest('hex');
// ************* TASK 3: CALCULATE THE SIGNATURE *************
// Create the signing key using the function defined above.
signingKey = getSignatureKey(secretKey, datestamp, region, serviceName);
// Sign the string_to_sign using the signing_key
signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest(
'hex');
// ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
// The signing information can be either in a query string value or in
// a header named Authorization. This code shows how to use a header.
// Create authorization header and add to request headers
authorizationHeader = algorithm + ' ' + 'Credential=' + accessKey + '/' +
credentialScope + ', ' + 'SignedHeaders=' + signedHeaders + ', ' +
'Signature=' + signature;
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0
var options = {
method: apiMethod,
host: apiHost,
path: apiEndpoint,
headers: {
'X-Amz-Date': amzdate,
'Authorization': authorizationHeader
}
};
callback = function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function(chunk) {
str += chunk;
});
console.log("CALLBACK",str);
//the whole response has been recieved, so we just print it out here
response.on('end', function() {
console.log('Complete: ' + str);
});
}
console.log(options);
https.request(options, callback).end();
I am getting signature mismatch error.
Complete: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>SignatureDoesNotMatch</Code><Resource>archivestorage/objectNameNotDecodedYet</Resource>
<Message>The request signature we calculated does not match the signature you provided. Check your secret access key and signing method.
</Message></Error>
Same header are passed via postman and it is working fine.
Can somebody help me out where I am making mistake ?
Thanks in advance