-
Notifications
You must be signed in to change notification settings - Fork 371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DELETE requests fail on Mono env #24
Comments
So I did some debugging on these 3: 1. Hmac256 implementation is broken on Mono.2. Canonicalized string is computed differently on two platforms.3. Request headers set is different.1. Hmac256 implementation is broken on Mono.This is not it. I copied CryptoUtility class over to mono and called it with the same inputs that Windows calls it and produced same output. Also, this signing issue is not happening intermittently, it's consistent. 2. Canonicalized string is computed differently on two platforms.I added some log statements to SharedKeyAuthenticationHandler.SignRequest and used my private build for debugging on both Windows and Mono. Canonicalized string computed same on both platforms (only random & time values differ):
(I can add base64 values for those if needed.) But this also does not seem like the issue, so I thought, maybe modified headers are actually different than what's computed on canonicalization 3. Request headers set is differentBut they also look the same. Here's what On Mono:
On Windows
(note these are different requests from the ones that I used in canonicalized string debugging.) What else?As I said, right now the only difference seemed like extra So I am clueless at the moment, I probably need to install some mitmproxy on Mac & get Fiddler to capture storage https requests. I don't have experience in any, so any help is appreciated. Hope all those helps. |
Note, we have not explicitly tested the client library on mono. That being said, one of the issues we have run into on some platforms is that the request wrapper object t(httpurlconnection / webrequest etc) inserts headers into the request without letting the client know. For example the HttpUrlConnection in Java will insert the Content-Length, but not allow the client to know what value it is sending. From the server perspective if it receives one of these headers that make up the canonicalized string it will attempt to honor them which in turn causes the authentication failure as the calculated signatures now differ. My guess is that you may be hitting something similar to this where the service is actually receiving Content-Length:0 even thought the client object does not expose this and it is not included in the string to sign. If you are debugging with the source and building a simple trick would be to edit the AppendCanonicalizedContentLengthHeader method (https://github.com/WindowsAzure/azure-storage-net/blob/master/Lib/Common/Core/Util/AuthenticationUtility.cs#L166) to append 0 in the case of deletes (under mono) and see if this fixes your issue. Also note, to assist in debugging, if you enable logging you can get the string to sign to help debugging these issues in the future. |
I did enable the logging on operation context but I couldn't find where it does log. 😭 As far as I know, all modern HTTP/1.1 clients SHOULD send I don't know much about Fiddler, but when you send DELETE requests from Windows, does not .NET libraries automatically add Anyway, a fix may be needed :) Just saying. Thanks Joe. |
Please see here for more information about enabling logging : http://blogs.msdn.com/b/windowsazurestorage/archive/2013/09/07/announcing-storage-client-library-2-1-rtm.aspx Regarding Content-Length header, It is fine to send this header, however the client side abstraction must inform the application that it is doing so in order to authenticate properly. Regardless of platform it is fine to either send length=0 or not, so long as request.ContentLength reports the correct value to the client. (>-1L) so that it can be correctly signed. On windows this is not being sent automatically and hence it is not part of the canonicalized string, I believe what is happening in mono is that is sending this header, but when the client attampts to get the contentlength from the request it is not specified and therefore not part of the string to sign. |
Meanwhile I created Bug 17736 on Xamarin-Mono project. |
Technically Mono should give back the correct header value for content length if it is indeed setting it to zero. An interesting experiment would be to attempt to set it to -1Lmanually and see if it still shows up in the request. I wouldn't want to force all clients to explicitly start sending the 0 length content length for deletes, however we could do a mono workaround where when we detect we are running on mono (see user agent string) we can automatically assume content length is sent for deletes which would unblock this scenario. |
Setting Content-Length to -1, 0 or 1 (as strings) in SignRequest header throws
Anyway it's a Mono problem. Do you think headers['user-agent'].Contains('Unix') would suffice? |
I was using request.Headers.Add, apparently for the default headers that's not supported. Anyway, adding this to the SignRequest method solves it:
So adding this to all requests must have no harm except:
Determining the Mono environment as a temporary workaround might be expensive if we use the recommended way: A cheaper way to determine if running on Mono could be assuming
So which way should we go? |
Fixed in Mono per request. https://bugzilla.xamarin.com/show_bug.cgi?id=17736 hoping to get and try soon. |
I ran into the same error when attempting to run: Turned out that my system time was off by a few hours. |
I am using client v3.0.3.0 on Mac OS X with Mono. All DELETE requests (delete container, CloudBlockBlob.Delete, CloudPageBlob.Delete) are failing with HTTP 403 Forbidden:
Seems like a signing issue. Repro is rather easy:
It was also the same on v3.0.2.x, I just upgraded today to see if it's a known issue. Same version works fine on Windows. And please note, it's just DELETE operations, all others work fine.
Here's a dump of
RequestEventArgs.Request.Header.ToString()
caught inOperationContext.ResponseReceived
event on both platforms,OS X:
Windows:
The only difference I see is
Content-Length: 0
added on Windows probably while sending the request. I'll try to see if it is missing while signing. I'll be investigating a bit.The text was updated successfully, but these errors were encountered: