I am generating a signature for doing client side posting to s3 in node on the back end and submitting it via jquery-file-upload on the client. My signature generation looks like the following:
app.post('/api/v1/s3', function(req, res){
var data = utils.getReqJson(req.body);
var mime_type = mime.lookup(data.filename);
var expire = moment().utc().add('hour', 1).toJSON("YYYY-MM-DDTHH:mm:ss Z");
var policy = JSON.stringify({
"expiration": expire,
"conditions": [
{"bucket": aws_bucket},
["starts-with", "$key", aws_bucket_dir],
{"acl": "private"},
{"success_action_status": "201"},
["starts-with", "$Content-Type", ''],
["content-length-range", 0, max_filesize]
]
});
var base64policy = new Buffer(policy).toString('base64');
var signature = crypto.createHmac('sha1', process.env.AWS_SECRET).update(base64policy).digest('base64');
signature = encodeURIComponent(signature.trim());
signature = signature.replace('%2B','+');
var file_key = uuid.v4();
res.json({ policy: base64policy,
signature: signature,
key: aws_bucket_dir + file_key + "_" + data.filename,
contentType: mime_type,
aws_access: process.env.AWS_ACCESS_KEY,
bucket_dir: aws_bucket_dir,
bucket: aws_bucket
});
});
Then on the front end I have the following code:
this.$().fileupload({
dataType: 'json',
type: 'POST',
autoUpload: true,
add: function (e, data) {
$.ajax({
url: window.ENV.api_url+'/' + window.ENV.api_namespace + '/s3',
type: 'POST',
dataType: 'json',
data: {
"filename": data.files[0].name
},
async: false,
success: function(retdata) {
//do actual upload stuff now.
data.url = 'https://'+retdata.bucket+'.s3.amazonaws.com/';
data.formData = {
key: retdata.key,
AWSAccessKeyId: retdata.aws_access,
acl: 'private',
policy: retdata.policy,
signature: retdata.signature,
success_action_status: 201,
"Content-Type": retdata.contentType
};
data.submit()
.success(function (result, textStatus, jqXHR) {
console.log('Success: ' + result);
})
.error(function (jqXHR, textStatus, errorThrown) {
console.log('Error: ' + errorThrown);
console.log(jqXHR);
console.log('Status: ' + textStatus);
});
console.log(retdata);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log('AJAX: ' + xhr);
console.log('AJAX: ' + thrownError);
}
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
});
It seems as though I am submitting the correct form data to match my signature generation, but I am getting the following errors every time I try to submit:
SignatureDoesNotMatch - The request signature we calculated does not match the signature you provided. Check your key and signing method.
I am struggling to figure out what I might be doing wrong, if anyone can help I would appreciate it.