Just started working with the node.js aws client to generate a presigned url and send it to the browser for the user to upload the file, but I get the following message:
SignatureDoesNotMatch The request signature we calculated does not match the signature you provided. Check your key and signing method.
I have references quite a few links and it seems really basic, but I seem to be failing
https://github.com/aws/aws-sdk-js/issues/251
Direct Browser Upload to S3 with Meteor, jQuery and the AWS SDK
https://forums.aws.amazon.com/thread.jspa?messageID=556839
Either, I am completely stupid or the sdk is really difficult to use
node:
var putParams = {
Bucket: config.aws.s3UploadBucket,
Key: filename,
ACL: 'public-read',
Expires: 120,
Body: '',
ContentMD5: 'false'
};
s3.getSignedUrl('putObject', putParams, function (err, url) {
if (!!err) {
console.error(err);
res.json({error: ''});
return;
}
res.json({
'awsAccessKeyId': config.aws.accessKeyId,
's3bucket': config.aws.s3UploadBucket,
's3key': filename,
's3policy': s3policy.policy,
's3signature': s3policy.signature,
'url': url
});
});
client:
var fd = new FormData();
fd.append('file', file);
return new RSVP.Promise(function(resolve, reject) {
$.ajax({
url: uploadObj.url,
data: fd,
processData: false,
contentType: false,
crossDomain: true,
type: 'PUT',
success: function(json, textStatus, jqXhr){
console.log(json);
resolve(json);
},
error: function(jqXhr, textStatus, errorThrown){
reject({ jqXhr: jqXhr, textStatus: textStatus, errorThrown: errorThrown});
}
});
});
UPDATE: In response to some of the comments, I did put in a valid CORS for the bucket.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I've been fighting this as well. This is what worked for me and I was getting the exact same error as you.
On the server side, I'm using AWS-SDK for nodejs
var params = { Bucket: "bucketname", Key: "filename", ContentType: "multipart/form-data" } var url = s3.getSignedUrl('putObject', params, function(err, url) { console.log(url); }
Client Side
$.ajax({ method: "PUT", headers: {"Content-Type": "multipart/form-data"}, processData: false, url: "http://AWSURL?AWSAccessKeyId..." })
Your cors looks right to me, the key was ensuring that the headers for Content-Type matched exactly
Thanks a ton to jeremy and kungfoo! I was having the same issues, though an added wrinkle when using Python's boto library. If you're generating the URLs from Python, a minimum working config seems to be:
Boto3 works but not Boto2!
import boto3
conn = boto3.client('s3', ...)
url = conn.generate_presigned_url('put_object', {
'Bucket': my_bucket_name,
'Key': my_bucket_key,
'ContentType': 'my_content_type'
}, 300)
The minimum required rules seem to be:
<CORSRule>
<AllowedOrigin>*.mydomain.com</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
Using jQuery, and being sure to keep the same content type as before:
$.ajax({
type: "PUT",
headers: {"Content-Type": "my_content_type"},
url: url_from_server,
data: my_data_as_string,
processData: false,
contentType: false,
crossDomain: true,
cache: false
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With