Amazon S3 Post Api, And Signing A Policy With Nodejs
Solution 1:
Ok, I finally figured it out. After playing the random guessing game for a VERY long time, I thought to myself
"maybe i need to sign the base64 encoded policy" - me
and BAM that was it.
I also re-ordered the conditions to match how the form is posting, though I'm not sure this makes a difference.
var crypto = require("crypto");
var config = require("../../amazonConfig.json");
exports.createS3Policy = function(contentType, callback) {
var date = newDate();
var s3Policy = {
"expiration": "2014-12-01T12:00:00.000Z", // hard coded for testing"conditions": [
["starts-with", "$key", "somefolder/"],
{"bucket": "my-bucket-name"},
{"acl": "public-read"},
["starts-with", "$Content-Type", contentType],
{"success_action_redirect": "http://example.com/uploadsuccess"},
]
};
// stringify and encode the policyvar stringPolicy = JSON.stringify(s3Policy);
var base64Policy = Buffer(stringPolicy, "utf-8").toString("base64");
// sign the base64 encoded policyvar signature = crypto.createHmac("sha1", config.secretKey)
.update(newBuffer(base64Policy, "utf-8")).digest("base64");
// build the results objectvar s3Credentials = {
s3Policy: base64Policy,
s3Signature: signature
};
// send it backcallback(s3Credentials);
};
Hopefully this will help others that run in to the same problem.
Solution 2:
I modified a bit previous example, because it didn't work for me: amazon returned an error about broken signature.
Here is how the signature should be created for Browser-Based Uploads Using POST (AWS Signature Version 4)
http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html
varCryptoJS= require("crypto-js");
varaccessKeyID="PUT YOUR DATA";
varsecretAccessKey="PUT YOUR DATA";
varbucket="PUT YOUR BUCKET NAME";
varregion="eu-central-1"; // overwrite with your regionvarfolder="users/"; // overwrite with your foldervarexpiration="2015-09-28T12:00:00.000Z"; // overwrite datevardate="20150927"; // overwrite datevarserviceName="s3";
function getSignatureKey(key, dateStamp, regionName, serviceName) {
varkDate= CryptoJS.HmacSHA256(dateStamp, "AWS4" + key);
varkRegion= CryptoJS.HmacSHA256(regionName, kDate);
varkService= CryptoJS.HmacSHA256(serviceName, kRegion);
varkSigning= CryptoJS.HmacSHA256("aws4_request", kService);
return kSigning;
}
vars3Policy= {"expiration": expiration,
"conditions": [
{"bucket": bucket},
["starts-with", "$key", folder],
{"acl": "public-read"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
["starts-with", "$x-amz-meta-tag", ""],
{"x-amz-credential": accessKeyID + "/" + date + "/" + region + "/" + serviceName +"/aws4_request"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": date + "T000000Z" }
]
};
varbase64Policy=newBuffer(JSON.stringify(s3Policy), "utf-8").toString("base64");
console.log('base64Policy:', base64Policy);
varsignatureKey= getSignatureKey(secretAccessKey, date, region, serviceName);
vars3Signature= CryptoJS.HmacSHA256(base64Policy, signatureKey).toString(CryptoJS.enc.Hex);
console.log('s3Signature:', s3Signature);
Next generated base64Policy and s3Signature i used in the form for uploading. Example is here: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html
Very important is to check that you have the same fields and values in the html form and in your policy.
Solution 3:
I continued to have issues, so I worked through them and posted my solution here:
https://github.com/nikkwong/ng2-s3-uploader
In short, if you go with scabbiaza's answer in building the signature, make sure to build the form like so:
let formData = new FormData;
formData.append('acl', xAmzAcl);
formData.append('Content-Type', file.type);
formData.append('X-Amz-Date', xAmzDate);
formData.append('x-amz-server-side-encryption', xAmzServerSideEncryption);
formData.append('x-amz-meta-uuid', xAmzMetaUuid);
formData.append('X-Amz-Algorithm', xAmzAlgorithm);
formData.append('X-Amz-Credential', xAmzCredential);
formData.append('X-Amz-Signature', s3Signature);
formData.append('Policy', base64Policy);
formData.append('key', folder + '/' + file.name);
// File field must come last!
formData.append('file', file);
Solution 4:
AWS SDK now provides an easy way to create the POST policy with createPresignedPost().
Docs: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property

Post a Comment for "Amazon S3 Post Api, And Signing A Policy With Nodejs"