Phil
Phil

Reputation: 7607

AWS S3 - 400 Bad Request when PUTting file via pre-signed URL

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....

Upvotes: 0

Views: 3856

Answers (1)

Arun Kamalanathan
Arun Kamalanathan

Reputation: 8603

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

Upvotes: 1

Related Questions