Why is my S3 pre-signed request invalid when I set the override of the response header containing "+"?

I am using the Amazon.NET SDK to create a pre-signed URL, for example:

public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition) { ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = contentType; if (!string.IsNullOrWhiteSpace(contentDisposition)) { headerOverrides.ContentDisposition = contentDisposition; } GetPreSignedUrlRequest request = new GetPreSignedUrlRequest() .WithBucketName(bucketName) .WithKey(objectKey) .WithProtocol(Protocol.HTTPS) .WithExpires(DateTime.Now.AddMinutes(6)) .WithResponseHeaderOverrides(headerOverrides); string url = S3Client.GetPreSignedURL(request); return new RedirectResult(url, permanent: false); } 

This works fine except that my contentType contains + in it. This happens when I try to get an SVG file, for example, which gets the image/svg+xml content type. In this case, S3 throws a SignatureDoesNotMatch error.

The error message shows StringToSign as follows:

 GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml 

Notice the place in the response-content type where it now says image/svg xml instead of image/svg+xml . It seems to me that this is causing the problem, but how to fix it correctly?

Should I encode my content type? Include it in quotation marks or something else? The documentation says nothing about this.

+6
source share
2 answers

Update

This error has been fixed since version 1.4.1.0 of the SDK.


Bypass

This is a confirmed bug in the AWS SDK , so until they release a fix, I am going to crack this one to get everything working:

Specify the type of content as you want it to appear in the response header. So, if you want S3 to return the image/svg+xml content type, set it exactly like this:

 ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = "image/svg+xml"; 

Now, go ahead and generate a pre-signed request, as usual:

 GetPreSignedUrlRequest request = new GetPreSignedUrlRequest() .WithBucketName(bucketName) .WithKey(objectKey) .WithProtocol(Protocol.HTTPS) .WithExpires(DateTime.Now.AddMinutes(6)) .WithResponseHeaderOverrides(headerOverrides); string url = S3Client.GetPreSignedURL(request); 

Finally, “fix” the resulting URL with the correct URL for your content type:

 url = url.Replace(contentType, HttpUtility.UrlEncode(contentType)); 

Yes, this is a dirty workaround, but hey, this works for me! :)

+4
source

Strange - I was able to reproduce this easily, with the following observed behavior:

  • replacing + in the URL generated by GetPreSignedURL() with its encoded form %2B , we get a working URL / signature
    • this is true, regardless of whether / is replaced by its encoded form %2F or not
  • encoding up-type content before calling GetPreSignedURL() , for example. using the HttpUtility.UrlEncode Method gives invalid signatures regardless of any changes to the generated URL.

Considering how long this functionality has been available, this is somewhat surprising, but I still consider it a mistake - so it would be better to find out about it in the Amazon Simple Storage Service Forum .
Update: I just realized that you already asked the same question and the error was confirmed, so the correct answer can be understood over time by tracking the Response from the AWS team ;)
Update: This error has been fixed since version 1.4.1.0 in the SDK.

+3
source

Source: https://habr.com/ru/post/907141/


All Articles