Reputation: 9664
I am trying to upload data to an s3 bucket from the browser. I have generated a pre-signed url but I get a 403 forbidden response.
My server code is
const s3 = new AWS.S3({
accessKeyId: settings.resourceBucketKey,
secretAccessKey: settings.resourceBucketSecret,
region: 'eu-west-1'
})
const params = {
Bucket: 'my-bucket',
Key: 'photo.png',
ContentType: 'image/png',
ACL: 'authenticated-read',
}
const url = s3.getSignedUrl('putObject', params)
console.log(url)
My client code is (using the generated url)
const input = $('#myinput')
input.on('change', (res) => {
var theFormFile = $('#myinput').get()[0].files[0];
$.ajax({
url: url,
type: 'PUT',
contentType: 'image/png',
processData: false,
data: theFormFile,
}).success(function(){
alert('success')
})
}, false)
I have set cors on on the bucket to:
<?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>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
But I still get 403 forbidden on the response. The image I am trying to upload is call 'photo.png'. Am I missing something here?
Upvotes: 5
Views: 8705
Reputation: 7475
Full implementation of getting signed url from browser - enjoy!
<body>
<img height="200" width="200">
<script>
var mimes = {
'jpeg': 'data:image/jpeg;base64,'
};
AWS.config.update({
signatureVersion: 'v4',
region: 'us-east-1',
accessKeyId: '',
secretAccessKey: ''
});
var bucket = new AWS.S3({params: {Bucket: 'xxxx'}});
function encode(data)
{
var str = data.reduce(function(a,b){ return a+String.fromCharCode(b) },'');
return btoa(str).replace(/.{76}(?=.)/g,'$&\n');
}
function getUrlByFileName(fileName,mimeType) {
return new Promise(
function (resolve, reject) {
bucket.getObject({Key: fileName}, function (err, file) {
var result = mimeType + encode(file.Body);
resolve(result)
});
}
);
}
function openInNewTab(url) {
var redirectWindow = window.open(url, '_blank');
redirectWindow.location;
}
getUrlByFileName('sprites.png', mimes.jpeg).then(function(data) {
//openInNewTab(data);
document.querySelector('img').src = data;
});
</script>
</body>
Upvotes: -5
Reputation: 3404
The creator (you) of the pre-signed URL must have permissions to be able to access the S3 bucket to upload a file. This is more eloquently described in the S3 documentation:
A pre-signed URL gives you access to the object identified in the URL, provided that the creator of the pre-signed URL has permissions to access that object. That is, if you receive a pre-signed URL to upload an object, you can upload the object only if the creator of the pre-signed URL has the necessary permissions to upload that object.
Make sure the IAM user that is creating the pre-signed URL has the necessary permissions.
Upvotes: 5