odysseyscience / react-s3-uploader

React component that renders an <input type="file"/> and automatically uploads to an S3 bucket

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Upload error: Upload error: 403 — `SignatureDoesNotMatch `

gastongouron opened this issue · comments

commented

Hello, and thank you for the amazing piece of code react-s3-uploader seems to be. I'm sorry in advance if this issue is code related but after stumbling for a few days agains this and reading every possible issue on the list, here i am.

The context:

  • Rails 5 api backend using 'aws-sdk', '~> 3' gem to talk to S3
  • ReactJS client using react-s3-uploader

So far, everything seems to work out of the box. Here is the method that returns the presignedUrlin rails controller by using the filename parameter:

# S3_controller#sign

def sign
    filename = params["objectName"]
    content = params["contentType"]

    signer = Aws::S3::Presigner.new
    signed = signer.presigned_url(:put_object,
                     bucket: 'encorencore',
                     key: "uploads/#{filename}",
                     acl: 'public-read',
                     content_type: content)

    render json: { signedUrl: signed }
end

I have been uploading successfully files to amazon with this backend for the sake of testing so I'm most likely certain that this issue is not related to credentials. Meanwhile, On the frontend, I use the ReactS3Uploader with the following props:

<ReactS3Uploader
            signingUrl={`/s3/presigned_url`}
            signingUrlMethod="GET"
            accept="image/*"
            s3path="/uploads"
            preprocess={this.onUploadStart}
            onSignedUrl={this.onSignedUrl}
            onProgress={this.onUploadProgress}
            onError={this.onUploadError}
            onFinish={this.onUploadFinish}
            signingUrlHeaders={ this.headers }
            // signingUrlQueryParams={{ additional: query-params }}
            signingUrlWithCredentials={ true }
            uploadRequestHeaders={{ 'x-amz-acl': 'public-read' }}  // this is the default
            contentDisposition="auto"
            scrubFilename={(filename) => filename.replace(/[^\w\d_\-.]+/ig, '')}
            inputRef={cmp => this.uploadInput = cmp}
            autoUpload={true}
            /> 

What happens:

  • Client updates a file
  • rails gets called with the filename
  • rails calls amazon through the gem and creates the signed_url
  • rails replies to the client with JSON whose payload contains { signedUrl: the_url }
  • client gets the url and starts an OPTION call to amazon that results in 200
  • The error: clients sends a put to amazon with the file data and get a 403.

Here is a preview of what it looks like in my browser:

screen shot 2018-10-22 at 07 17 45

When I manually visit the put url provided by the server I'm reaching a web page with some XML, the message show the following error:

message

Right now, I'm not sure where the problem comes from and the amazon error message is not specific enough for me to understand if the problem comes from the backend signature (as the message suggests), or from the client props, or event worse from S3 bucket setup itself.

What I have tried without success:

  1. Updating the CORS config of this bucket such as:
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

-2. Updating the bucket policy (also tried with a wildcard for Principal with same results):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1540188247000",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::707682590005:root"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::encorencore/*"
        }
    ]
}

-3. tweeking every possible option on both rails and react.

I'm not loosing hope but I secretly wish someone encountered a similar problem in a similar context and can come up with a solution or some sort of thing I wouldn't have though about. Please, if you have any input, do not hesitate!

Thanks a lot for your time <3

dupe; see comment on #191