HELP!!!!!!!!! I need to generate the authorization header and the date so I can send API calls but it wont work not sure what im doiong wrong.

0

const crypto = require('crypto');

class AwsV4 { constructor(accessKeyID, secretAccessKey) { this.accessKeyID = accessKeyID; this.secretAccessKey = secretAccessKey; this.currentDateObject = new Date(); this.xAmzDate = this.getTimeStamp(this.currentDateObject); this.currentDate = this.getDate(this.currentDateObject); }

setPath(path) {
    this.path = path;
}

setServiceName(serviceName) {
    this.serviceName = serviceName;
}

setRegionName(regionName) {
    this.regionName = regionName;
}

setPayload(payload) {
    this.payload = payload;
}

setRequestMethod(method) {
    this.httpMethodName = method;
}

addHeader(headerName, headerValue) {
    this.awsHeaders = this.awsHeaders || {};
    this.awsHeaders[headerName] = headerValue;
}

prepareCanonicalRequest() {
    let canonicalURL = '';
    canonicalURL += this.httpMethodName + '\n';
    canonicalURL += this.path + '\n';

    // Add the missing line to include the CanonicalQueryString
    canonicalURL += '' + '\n'; // Use an empty string as there are no query string parameters in this case

    let signedHeaders = '';

    // Add x-amz-date header
    this.addHeader('x-amz-date', this.xAmzDate);

    // Sort headers lexicographically by header name (lowercase)
    const sortedHeaderKeys = Object.keys(this.awsHeaders).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
    for (const key of sortedHeaderKeys) {
        if (key !== 'Accept' && key !== 'Accept-Language' && key !== 'Content-Type') {
            signedHeaders += key.toLowerCase() + ';';
            canonicalURL += key.toLowerCase() + ':' + this.awsHeaders[key] + '\n';
        }
    }
    canonicalURL += '\n';
    this.strSignedHeader = signedHeaders.slice(0, -1);
    canonicalURL += this.strSignedHeader + '\n';
    canonicalURL += this.generateHex(this.payload);
    return canonicalURL;
}





prepareStringToSign(canonicalURL) {
    let stringToSign = '';
    stringToSign += 'AWS4-HMAC-SHA256' + '\n';
    stringToSign += this.xAmzDate + '\n';
    stringToSign += this.currentDate + '/' + this.regionName + '/' + this.serviceName + '/' + 'aws4_request' + '\n';
    stringToSign += this.generateHex(canonicalURL);
    return stringToSign;
}

calculateSignature(stringToSign) {
    const signatureKey = this.getSignatureKey(this.secretAccessKey, this.currentDate, this.regionName, this.serviceName);
    const signature = crypto.createHmac('sha256', signatureKey).update(stringToSign).digest('hex');
    return signature;
}
getHeaders() {
    const canonicalURL = this.prepareCanonicalRequest();
    const stringToSign = this.prepareStringToSign(canonicalURL);
    const signature = this.calculateSignature(stringToSign);
    const authorizationHeader = this.buildAuthorizationString(signature);

    this.awsHeaders['Authorization'] = authorizationHeader;
    this.awsHeaders['x-amz-date'] = this.xAmzDate;

    return this.awsHeaders;
}

getUpdatedHeaders() {
    this.setPath('/paapi5/getitems');
    this.setServiceName('ProductAdvertisingAPI');
    this.setRegionName('us-east-1');
    this.setRequestMethod('POST');
    this.setPayload(payloadJsonString); // Use the actual payload JSON string
    
    this.addHeader('Host', 'webservices.amazon.com');
    this.addHeader('Content-Encoding', 'amz-1.0');
    this.addHeader('Content-Type', 'application/json; charset=UTF-8');
    this.addHeader('x-amz-date', this.xAmzDate); // Move this line up
    this.addHeader('X-Amz-Target', 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.GetItems');

    const headers = this.getHeaders();

    return {
        'Authorization': headers['Authorization'],
        'X-Amz-Date': headers['x-amz-date']
    };
}



buildAuthorizationString(signature) {
return 'AWS4-HMAC-SHA256' + ' ' + 'Credential=' + this.accessKeyID + '/' + this.getDate(this.currentDateObject) + '/' + this.regionName + '/' + this.serviceName + '/' + 'aws4_request' + ' ' + 'SignedHeaders=' + this.strSignedHeader + ' ' + 'Signature=' + signature;

}

generateHex(data) {
    return crypto.createHash('sha256').update(data).digest('hex');
}

getSignatureKey(key, date, regionName, serviceName) {
    const kSecret = 'AWS4' + key;
    const kDate = crypto.createHmac('sha256', kSecret).update(date).digest();
    const kRegion = crypto.createHmac('sha256', kDate).update(regionName).digest();
    const kService = crypto.createHmac('sha256', kRegion).update(serviceName).digest();
    const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest();
    return kSigning;
    }
getTimeStamp(date) {
    return date.toISOString().replace(/[:-]|\.\d{3}/g, '');
}
    
getDate(date) {
    const year = date.getUTCFullYear();
    const month = ('0' + (date.getUTCMonth() + 1)).slice(-2);
    const day = ('0' + date.getUTCDate()).slice(-2);
    return `${year}${month}${day}`;
}

} const awsV4 = new AwsV4('AKIAI6QL7ST37VECNI7A', 'ZnZS++sxYuDGxP8VOSEG2uZd8Qmtup9F51wHgOkw'); const payload = { "ItemIds": [ "B01M6V8CP4" ], "Resources": [ "CustomerReviews.Count", "CustomerReviews.StarRating", "Images.Variants.Large", "ItemInfo.Features", "Offers.Listings.Promotions", "Offers.Summaries.LowestPrice" ], "PartnerTag": "timstools03-20", "PartnerType": "Associates", "Marketplace": "www.amazon.com" };

const payloadJsonString = JSON.stringify(payload);

// Pass the JSON string to setPayload() awsV4.setPayload(payloadJsonString); const updatedHeaders = awsV4.getUpdatedHeaders();

console.log(updatedHeaders);

1 Answer
0

Important: I'd note that you appear to have pasted your security access keys into the code above - please delete those and consider them to be compromised. Don't ever reveal your Access Key and your Secret Access Key in public forums - it can take only seconds for someone to try and take advantage of them.

Rather than try and debug the code above, I'd suggest looking at the documentation (which I suspect you already have) and more specifically at the JavaScript example.

profile pictureAWS
EXPERT
answered a year ago
  • I did notice that after posting. But I deleted them immediately after I sent it. I am looking for a solution to use the PA API on my Bubble site but the SDK is just not a good option. Only need a script to build the authorization and x-amz-date headers. It seems I am making an error somewhere but I don't get much feedback on what the actual error is.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions