question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SignatureDoesNotMatch for multipart upload using signed URLs.

See original GitHub issue

I have a setup where I start a multipart upload from a boto3 client, that also creates signed URLs for a javascript client to use.

I have tried a bunch of different configurations and parameters, but my PUT requests from the javascript client always are forbidden due to a SignatureDoesNotMatch error.

I found that the documentation is not really extensive on ClientMethods, on what and how is going to get signed when calling generate_presigned_url, thus it’s very difficult to know what headers to send and how to make the PUT request from the javascript code.

As a side note: a similar setup is working in the project for traditional uploads with a single signed URL, using the put_object ClientMethod.

Steps to reproduce The boto3 code:

@classmethod
def create_multipart_upload(cls, key):
    return cls.s3_client.create_multipart_upload(
        Bucket=config.AWS_S3_BUCKET_NAME,
        Key=key,
        # ACL='public-read',  # I have tried all (or at least a lot of) the combinations of these commented parameters
        # ContentType='binary/octet-stream'
    )
    
[...]

@classmethod
def generate_multipart_presigned_urls(cls, key, upload_id, parts):
    return [
        {
            'partNumber': p['partNumber'],
            'url': cls.s3_client.generate_presigned_url(
                ClientMethod='upload_part',
                Params={
                    'Bucket': current_config.AWS_S3_BUCKET_NAME,
                    'Key': key,
                    'UploadId': upload_id,
                    'PartNumber': p['partNumber'],
                    # 'ContentLength': p['contentLength'],  # I have also tried combinations of these parameters
                    # 'ContentMD5': p['md5']
                    # 'ContentType': 'binary/octet-stream',  # These two are not acceptable here
                    # 'ACL': 'public-read'
                },
                HttpMethod='PUT',
                ExpiresIn=60000,
            )
        }
        for p in parts
    ]

The javascript code:

const uploadMultipartChunks = (chunks) => {
  const promises = []

  for (const c of chunks) {
    // c.url comming from boto3 generate_presigned_url
    promises.push(axios.put(c.url, c.blob, {
      crossDomain: true,
      headers: {
        // Different combinations of headers were also tested here
        // 'x-amz-acl': 'public-read',
        // 'Content-Type': 'binary/octet-stream',
        // 'Content-MD5': c.md5,
        // 'Content-Length': chunkSize
      }
    }))
  }
  const resParts = await Promise.all(promises)
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
github-actions[bot]commented, Aug 24, 2021

Greetings! It looks like this issue hasn’t been active in longer than a week. We encourage you to check if this is still an issue in the latest release. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one.

1reaction
stobrien89commented, Aug 17, 2021

Hi @psancheztriller,

Thanks for letting us know! The signatures are calculated based on the parameters/client method provided here. If you turn on debug logs by adding boto3.set_stream_logger('') to your Python code, you’re able to see which auth type is being used.

I realize you may have this somewhere in your code already, but just thought I’d throws this out there in case you weren’t aware: you’ll need to use the complete_multipart_upload api to re-assemble the parts once you’re finished using the upload_part api. A brief example of this is shown here.

I still think it would be helpful to see logs of the HTTP request/response from your JS code and snippets of any bucket policies (with sensitive information such as account numbers redacted) to further troubleshoot this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SignatureDoesNotMatch error when uploading to s3 via a pre ...
We were receiving the presigned url, but when tried to download the file with that presign url, it said "signature does not match"....
Read more >
AWS S3 Presigned Url Error SignatureDoesNotMatch
I use Laravel as an API and it creates a presigned URL for AWS S3. Then i use this generated URL to upload...
Read more >
S3 Signature Does Not Match Error When Using A Pre Signed ...
Using the ng-file-upload package, I setup my promises to call the API, return the pre-signed url, then use this url to upload the...
Read more >
"Signature Does Not Match" when putting to presigned spaces ...
I am using the aws-sdk in Node.js to generate a presigned putObject upload url for use with DigitalOcean Spaces. The url gets generated...
Read more >
Generating a presigned URL to upload an object
Upload Amazon S3 objects using presigned URLs when someone has given you permissions to access the object identified in the URL.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found