title: AWS S3 file upload with pre-signed url using JavaScript gets 403 Forbidden error(AccessDenied)
body: <p>I'm trying to upload an image to my S3 bucket using JavaScript with pre-signed url.</p>
  <p>This is my JavaScript Code:</p>
  <pre><code>    const formData = new FormData();
      formData.append(&quot;file&quot;, event.target.files[0]);
      formData.append(&quot;Content-Type&quot;, event.target.files[0].type);
      Object.entries(preSignedFields).forEach(([key, value]) =&gt; {
          if (&quot;Content-Type&quot; === key) {
              return;
          }
          formData.append(key, value);
      })
      fetch(presignedUrl, {
          method: &quot;PUT&quot;,
          headers: { &quot;Content-Type&quot;: &quot;multipart/form-data&quot; },
          body: formData,
      })
          .then(response =&gt; console.log(response))
          .catch(error =&gt; console.log(error));
  </code></pre>
  <p>The constants presignedUrl and preSignedFields come from an api response. When I call the fetch method, I get 403 Forbidden error.</p>
  <p>This is headers information from chrome's dev tool, Network &gt; Headers:</p>
  <pre><code>Request URL: https://_____.s3.amazonaws.com/files/67189b29466c4341b6cdd422578ac9dd
  Request Method: PUT
  Status Code: 403 Forbidden
  Remote Address: _____
  Referrer Policy: no-referrer-when-downgrade
  Access-Control-Allow-Methods: GET, PUT, POST
  Access-Control-Allow-Origin: *
  Access-Control-Max-Age: 3000
  Connection: close
  Content-Type: application/xml
  Date: Thu, 30 Jul 2020 13:31:37 GMT
  Server: AmazonS3
  Transfer-Encoding: chunked
  Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
  x-amz-id-2: 0c22DYZoqcxQ9W8X3o8zwhrP+LveBJ2GSJoer5IA0pgo98hkPaMC0gfO9kUJ7LzB4TfECmyl47I=
  x-amz-request-id: _____
  Accept: */*
  Accept-Encoding: gzip, deflate, br
  Accept-Language: ja,en-US;q=0.9,en;q=0.8
  Connection: keep-alive
  Content-Length: 345706
  Content-Type: multipart/form-data
  Host: _____.s3.amazonaws.com
  Origin: http://localhost:3000
  Referer: http://localhost:3000
  Sec-Fetch-Dest: empty
  Sec-Fetch-Mode: cors
  Sec-Fetch-Site: cross-site
  User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;image.jpeg&quot;
  Content-Type: image/jpeg
  
  
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;Content-Type&quot;
  
  image/jpeg
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;acl&quot;
  
  public-read
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;key&quot;
  
  files/{hiding value}
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;AWSAccessKeyId&quot;
  
  {hiding value}
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;policy&quot;
  
  {hiding value}
  ------WebKitFormBoundaryHh0fScf4jkdjsk94
  Content-Disposition: form-data; name=&quot;signature&quot;
  
  {hiding value}
  ------WebKitFormBoundaryHh0fScf4jkdjsk94--
  </code></pre>
  <p>My S3's Cors settings is this:</p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  &lt;CORSConfiguration xmlns=&quot;http://s3.amazonaws.com/doc/2006-03-01/&quot;&gt;
  &lt;CORSRule&gt;
      &lt;AllowedOrigin&gt;*&lt;/AllowedOrigin&gt;
      &lt;AllowedMethod&gt;GET&lt;/AllowedMethod&gt;
      &lt;AllowedMethod&gt;PUT&lt;/AllowedMethod&gt;
      &lt;AllowedMethod&gt;POST&lt;/AllowedMethod&gt;
      &lt;MaxAgeSeconds&gt;3000&lt;/MaxAgeSeconds&gt;
      &lt;AllowedHeader&gt;*&lt;/AllowedHeader&gt;
  &lt;/CORSRule&gt;
  &lt;/CORSConfiguration&gt;
  </code></pre>
  <p>I can't find what's wrong with my implementation. Any advice will be greatly appreciated.</p>