Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting 403 (Forbidden) when uploading to S3 with a signed URL

I'm trying to generate a pre-signed URL then upload a file to S3 through a browser. My server-side code looks like this, and it generates the URL:

let s3 = new aws.S3({   // for dev purposes   accessKeyId: 'MY-ACCESS-KEY-ID',   secretAccessKey: 'MY-SECRET-ACCESS-KEY' }); let params = {   Bucket: 'reqlist-user-storage',   Key: req.body.fileName,    Expires: 60,   ContentType: req.body.fileType,   ACL: 'public-read' }; s3.getSignedUrl('putObject', params, (err, url) => {   if (err) return console.log(err);   res.json({ url: url }); }); 

This part seems to work fine. I can see the URL if I log it and it's passing it to the front-end. Then on the front end, I'm trying to upload the file with axios and the signed URL:

.then(res => {     var options = { headers: { 'Content-Type': fileType } };     return axios.put(res.data.url, fileFromFileInput, options);   }).then(res => {     console.log(res);   }).catch(err => {     console.log(err);   }); } 

With that, I get the 403 Forbidden error. If I follow the link, there's some XML with more info:

<Error> <Code>SignatureDoesNotMatch</Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> ...etc 
like image 878
Glenn Avatar asked Oct 22 '17 02:10

Glenn


People also ask

Why is S3 object URL Access Denied?

If you're trying to host a static website using Amazon S3, but you're getting an Access Denied error, check the following requirements: Objects in the bucket must be publicly accessible. S3 bucket policy must allow access to the s3:GetObject action. The AWS account that owns the bucket must also own the object.

What is signed URL in S3?

S3 pre-signed URLs are a form of an S3 URL that temporarily grants restricted access to a single S3 object to perform a single operation — either PUT or GET — for a predefined time limit. To break it down: It is secure — the URL is signed using an AWS access key.

How do I get pre-signed URL S3?

Sign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/ . In the Buckets list, choose the name of the bucket that contains the object that you want a presigned URL for. In the Objects list, select the object that you want to create a presigned URL for.


1 Answers

Your request needs to match the signature, exactly. One apparent problem is that you are not actually including the canned ACL in the request, even though you included it in the signature. Change to this:

var options = { headers: { 'Content-Type': fileType, 'x-amz-acl': 'public-read' } }; 
like image 124
Michael - sqlbot Avatar answered Sep 26 '22 02:09

Michael - sqlbot