0

My Request looks like this:

https://{my-bucket-name}.s3.amazonaws.com/{user-id}/{image-name}.jpeg?AWSAccessKeyId={key}&Content-Type=image%2Fjpeg&Expires=1597576628&Signature={signature}

where the {parts} are just censored but in the original response look correct, just like in a tutorial that I am doing.

I have allowed public access and set both CORS (which is why I get the pre-signed URL to upload to in the first place) as well as a bucket policy that contains this:

    {
        "Sid": "{sid}",
        "Action": [
            "s3:GetObject"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::{my-bucket-name}/*",
        "Principal": "*"
    }

So what might be the problem?

EDIT: adding PutObject to the policy did not help. I upload the file like this, from the React-client directly:

  const upload = await axios.put(uploadConfig.data.url, file, {
    headers: {
      'Content-Type': file.type
    }
  })

And I generate the pre-signed URL like this (note the putObject operation):

    s3.getSignedUrl('putObject', {
        Bucket: '{my-bucket-name}',
        ContentType: 'image/jpeg',
        Key: key
    }, (err, url) => res.send({key, url}));

Additional request headers set by the middleware/browser are:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en,de;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 104221
Content-Type: image/jpeg
Host: {my-bucket-name}.s3.amazonaws.com
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/blogs/new
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla....
10
  • How do you upload the file with the pre-signed url? Commented Aug 16, 2020 at 11:28
  • @Phil, I have deleted my answer. it was wrong. because you should never allow public write access. if the IAM credential used to generate the pre-signed url has sufficient permission to upload the file, the pre-signed url should work as well. Commented Aug 16, 2020 at 11:31
  • also if your pre-signed url is generated for getObject, you cannot perform a putObject operation using that pre-signed url Commented Aug 16, 2020 at 11:33
  • @ArunK I am doing this tutorial: udemy.com/course/advanced-node-for-developers where the teacher explains that the public access is ok, as we want a direct upload from the client, without wasting CPU-time of our backend, during the upload. For me this seems reasonable as long as you check only for file extensions and don't do deep file checks anyway. Commented Aug 16, 2020 at 11:39
  • what i meant was, giving putObject permission for every one in the bucket policy is bad. upload using pre-signed url is the correct way. public read is ok if you are ok with sharing your files with the whole world. Commented Aug 16, 2020 at 11:44

1 Answer 1

1

Please use AWS4-HMAC-SHA256. error message suggests to use signature version v4. it appears the generated signature in the pre-signed url is not v4. possibly signature version v2

please try specifying the signature version when generating the URL as below.

const s3 = new AWS.S3({signatureVersion: 'v4'})

Also make sure that you are using aws-sdk version greater than 2.68.0 according to the documentation

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, it works now. The v4 I fugured out myself, but the package update saved me some time :) Another thing I had to add was the custom region: new AWS.S3({ accessKeyId, secretAccessKey, signatureVersion: 'v4', region: 'eu-central-1' });
Yes you have figured the V4. Posted the answer to help others in the same situation. Please post an answer if you would like.
No no, it's alright, as I said, you helped me a lot, all credits to you, thanks :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.