77
Views
12
Comments
[Amazon Simple Storage Service (S3)] Content-Type parameter of Object_GetPreSignedUrl action for PUT endpoint
Application Type
Reactive

Dear authors, 

When using a generated url by Object_GetPreSignedUrl action for uploading file to S3 directly from PUT request in browser's JavaScript, AWS endpoint returned SignatureDoesNotMatch error. 

The request signature we calculated does not match the signature you provided. Check your key and signing method.

After a while investigation, I revealed that the Object_GetPreSignedUrl action doesn't assume that request contains Content-Type header. 
I used the generated url in the terminal window with curl command no Content-Type header, then the PUT uploading completed without any errors. 

On the other hand, when issuing PUT request from JavaScript of browser window, we have to use XMLHttpRequest class or fetch function. However these JavaScript functions can't remove Content-Type header from PUT request. So, using a generated url by Object_GetPreSignedUrl action will always result in a SignatureDoesNotMatch error.

To avoid the error, the Object_GetPreSignedUrl action must have an additional input parameter for Content-Type in order to direct PUT uploading from browser window. And the action have to use this  parameter to generate url by AWS SDK.

[Generating presigned URL for browser PUT needs Content-Type | Stack Overflow]
https://stackoverflow.com/a/41090784

[Content-Type is required for generating url for uploading | AWS SDK for .NET Documentation]
https://docs.aws.amazon.com/sdkfornet1/latest/apidocs/html/P_Amazon_S3_Model_GetPreSignedUrlRequest_ContentType.htm

Sample oml is attached.

Could you please check my request?

Best regards, 
Moriya Takasi

HeavyFilesS3.oml
2021-10-09 07-57-44
Stefan Weber
 
MVP

Hi. I wrote an article about uploading large files to S3 from the browser using a presigned URL a while ago https://itnext.io/file-uploads-from-outsystems-reactive-web-client-to-aws-s3-using-pre-signed-urls-18e9a42dee17. There is also a sample component on forge with the article https://www.outsystems.com/forge/component-overview/14747/aws-s3-direct-file-upload-sample-o11. That components includes a reusable widget you can use and adapt to your own likings.

Looking at your module I would assume the problem is that you explicitly set the content-type when using XMLHttpRequest. You should be able to simply remove that to get it work, as if none is specified the octet-stream content type is implicitly assumed. (see my component).

But besides that the official S3 connector misses some vital functionality.

Stefan


2018-03-29 06-28-54
Takasi Moriya
 
MVP

Thank you for checking my sample oml, Stefan.

When I removed the line for an explicitly Content-Type header from my oml, the app will stil leads same error (I attached new oml).
So, I think the forge should be implemented additional input parameter.

I will see your article and your forge.

Thanks again.

HeavyFilesS3_v9.oml
2018-03-29 06-28-54
Takasi Moriya
 
MVP

I ran Stefan's forge on my PE.

'success' message showed on browser screen. But the uploading was failed actually and the same error returned.

2021-10-09 07-57-44
Stefan Weber
 
MVP

Hi Takasi. I was just rechecking my demo and it successfully uploads the document. However if found out that I do not have added proper error checking in case of a Forbidden error. Could you check the developer console if you get a 403 error (console error). Maybe you are just missing the proper IAM permissions to Generate a presigned Url. I suggest - for demo purposes - to add the S3Fullaccess policy to the IAM credentials you are using.

PS: We are using - a slightly modified version of this widget - in most of our customer environments. So it should work :-)

2021-10-09 07-57-44
Stefan Weber
 
MVP

.... could it be that the filename (and therefor the S3 key) you try to upload contains Hiragana?

2018-03-29 06-28-54
Takasi Moriya
 
MVP

When the file name is 'test.png', the same error occurred.

I am using AmazonS3FullAccess policy.

And when using the generated url with curl command without Content-Type header, I can upload it to S3.
So, it doesn't seem to be caused by IAM permission.

Thank you for your investigation.

2021-10-09 07-57-44
Stefan Weber
 
MVP

Just posting my trace

But looking at this you are missing the region in the Host request header.

2021-10-09 07-57-44
Stefan Weber
 
MVP

PS: When using the official S3 connector you have to provide the Region Enum value. For eu-central-1 this becomes "EUCentral1". Generating a presigned url is fully offline so if you enter a wrong value for the region it is just omitted.

2018-03-29 06-28-54
Takasi Moriya
 
MVP

Hi Stefan, 

Sorry to be late.

I'm using 'USEast1' for specifying region. When I used 'us-east-1' by my mistake, generating URL failed. 
So, I think there is no error around specifying region.

And the host of endpoint URL generated doesn't contain region originally.
I don't know why this lack.  This may be because USEast1 is one of the initial AWS regions.

Using generated URL by curl command in the terminal window, uploading succeeded.

However, when appending Content-Type header with same command, uploading failed with SignatureDoesNotMatch error.

I can not remove Content-Type header from my request by XMLHttpRequest.
And I found the next link as I wrote at first.
So, I thought specifying Content-Type to generate presigned URL will lead a good result.

[Generating presigned URL for browser PUT needs Content-Type | Stack Overflow]
https://stackoverflow.com/a/41090784

Thank you so match.

2021-10-09 07-57-44
Stefan Weber
 
MVP

Seems like the useast1 region differs from eucentral1. I just set up a new bucket in the useast1 region and tried it. I now get the same error 403 with a signature mismatch. It still works in eucentral1. 

But. I found a post an repost.aws https://repost.aws/questions/QU4N4twu_CSq2GgOkRj-lXEA/get-s3-presigned-url-signaturedoesnotmatch where someone is indicating that this could be a temporary issue. The author mentioned that he just waited a couple of days and then it succeeded. There is also a blog post https://brijendrasinghrajput.medium.com/signaturedoesnotmatch-aws-s3-solved-7a02d8578f29 mentioning that there are some temporary s3 issues which resolved over time. I would suggest to wait another one or two days to make sure it is not a temporary issue (however I never experienced something like this, but iam soley using the eucentral1 region)

2018-03-29 06-28-54
Takasi Moriya
 
MVP

Thank you for information.
And thank you for reproducing the trouble on your site with useast1.

I'll wait a few days.

2018-03-29 06-28-54
Takasi Moriya
 
MVP

It's been more than a week since I first met the problem.
I still get the same error when I use USEast1.
And I confirmed that using EUCentral1 leads no error on my site same as Stefan wrote above.

I cloned the S3 connector forge and append an additional parameter for Content-Type to use PUT verb.
When using the cloned component, uploading from browser to both USEast1 and EUCentral1 completed successfully.
The cloned component is attached.

Revealed things:

  • Some AWS region has a different specification for validating a presigned URL for PUT request.
  • If a request contains a Content-Type header, USEast1 uses the Content-Type header to validate the request, regardless of whether Content-Type was specified at generating URL.
  • A PUT request by browser's JavaScript always includes Content-Type header and the header can't be removed.
  • Specifying Content-Type header at generating URL leads that uploading from browser to both USEast1 and EUCentral1 completed successfully.
  • So, we should specify Content-Type to generate URL for USEast1 as written in the stack overflow's post I wrote above.

So, I think that appending an additional parameter for PUT verb to official forge makes sense.

How do you think?

Clone of Amazon Simple Storage Service (S3).oap
Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.