3

How do I upload a file to S3 with a signed URL?

I tried the following:

  const AWS = require('aws-sdk');
  const s3 = new AWS.S3({ accessKeyId: "", secretAccessKey: "" });

  const url = s3.getSignedUrl("putObject", {
    Bucket: "SomeBucketHere",
    Key: "SomeNameHere",
    ContentType: "binary/octet-stream",
    Expires: 600
  });

But when I try uploading with Postman using the following steps, I get the SignatureDoesNotMatch error.

  1. PUT method with URL from the above code
  2. Body: binary (radio button), choose file, select a file to upload
  3. Hit Send

I can confirm that the IAM permissions are not the problem here. I have complete access to the Bucket.

What's wrong and how do I test my signed URL?

Faizuddin Mohammed
  • 4,118
  • 5
  • 27
  • 51

2 Answers2

5

This issue once caused me a lot of pain to get around.

All I had to do was add a header to the Postman request.

Header: Content-Type = binary/octet-stream

Once I changed this, the file uploads successfully.

Hope this saves someone a lot of trouble down the road.

Faizuddin Mohammed
  • 4,118
  • 5
  • 27
  • 51
1

Not sure if it's of any help anymore, but I believe you need to pass in the signature version.

In python you have something like:

import boto3 as boto3
from botocore.client import Config

...

s3_client = boto3.client('s3', config=Config(signature_version='s3v4'))
url = s3_client.generate_presigned_url(
            ClientMethod='put_object',
            Params={
                'Bucket': bucket,
                'Key': key,
            },
            ExpiresIn=60
        )
print url

So the equivalent in Javascript would be:

var AWS = require('aws-sdk');
var s3 = new AWS.S3({
  signatureVersion: 'v4',
});


exports.handler = (event, context, callback) => {
  const url = s3.getSignedUrl('putObject', {
    Bucket: '**\[YOUR-S3-BUCKET\]**',
    Key: 'mykey',
    Expires: 10,
  });


  callback(null, url);
};

Sources:

Presigned URL for S3 Bucket Expires Before Specified Expiration Time

Using pre-signed URLs to upload a file to a private S3 bucket