Implementing Put Block of Azure rest api? - rest

I am following this MSDN Reference (https://learn.microsoft.com/en-us/rest/api/storageservices/fileservices/put-block) to implement a rest call for Put Block.
I am coding in Java and I formed below Authorisation string and URL before signing.
PUT
364070
x-ms-blob-type:BlockBlob
x-ms-date:Fri, 20 Jan 2017 12:57:06 GMT
x-ms-version:2016-05-31
/xyz/mycontainer/imageBlock1
comp:block
sun.net.www.protocol.https.DelegateHttpsURLConnection:https://xyz.blob.core.windows.net/mycontainer/imageBlock1?comp=block&blockid=YmxvY2stMQ==
Error I am getting:
403
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
I read gaurav mantras post http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/. But, its not working for me.
Is there anything wrong with the string I am sending to sign or URL or
below httpConn Request Header.
The Http Header I am setting is:
httpConn.setRequestMethod("PUT");
httpConn.setRequestProperty("x-ms-blob-type", blobType);
httpConn.setRequestProperty("x-ms-date", date);
httpConn.setRequestProperty("x-ms-version", storageServiceVersion);
httpConn.setRequestProperty("Authorization", authorizationHeader);
httpConn.setRequestProperty("Content-Length",String.valueOf(blobLength) );
System.out.println(httpConn);
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.write(bytes);
wr.flush();
wr.close();
int response = httpConn.getResponseCode();

As I known, Put Block is a operation against Block Blobs. So, we do not need to specify x-ms-blob-type header. If you specify this in your HTTP header, you need to follow the following tutorial about constructing the Canonicalized Headers String:
Retrieve all headers for the resource that begin with x-ms-, including the x-ms-date header.
Convert each HTTP header name to lowercase.
Sort the headers lexicographically by header name, in ascending order. Each header may appear only once in the string.
Finally, append a new-line character to each canonicalized header in the resulting list. Construct the CanonicalizedHeaders string by concatenating all headers in this list into a single string.
So, based on your code, your canonicalized headers string looks like:
x-ms-blob-type:BlockBlob\nx-ms-date:Fri, 20 Jan 2017 12:57:06 GMT\nx-ms-version:2016-05-31\n
Moreover, the CanonicalizedResource you built is incorrect. Based on your code, it should look as follows:
/{account-name}/{container-name}/{blob-name}\nblockid:{block-id}\ncomp:block
Note: For more details about constructing the Canonicalized Resource String, you could refer to this official document.
The StringToSign would look like this:
And the traffic captured by Fiddler as follows:

Related

How to Validate HTTP message with JWS Detached

I wanted to know how I can validate HTTP messages with JWS Detached. Currently, I am receiving x-sign-jws request in header which looks like below
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..UXwjHxU3tFlrzPMupG04zROiEcHFQpCg3l7J4Axr1fE
I need to verify this at my end whether the request is right or not using my secrete Key
Ex: 12345678
I am using firebase/jwt and tried below code
$hed = getallheaders();
$recievedJwt = $hed["X-Sign-Jws"];
$decoded = JWT::decode($recievedJwt, $secret_key, array('JWT','HS256'));```
but I am not getting any result.
I searched on net I found the article which mentioned below steps:
Validation HTTP message with JWS Detached:
a) Get the HTTP header "x-sign-jws",
b) Get BASE64URL HTTP body
c) Put generate string b) into the Payload section
d) Validate JWS
But I am confused with how to get Base64URL HTTP body
Any help would be greatly appreciated since there are only a few articles available on this topic.
JWS format is base64url(header).base64url(payload).base64url(signature), note the dot delimiter between 3 components.
Detached JWS still contains 3 components but the payload is removed and provided elsewhere, usually the payload is provided in the HTTP Body.
To verify detached JWS, you need to add base64url encoded payload to the detached JWS. The payload is available from your HTTP Body.
For example;
x-sign-jws = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..UXwjHxU3tFlrzPMupG04zROiEcHFQpCg3l7J4Axr1fE
//split x-sign-jws into array using delimiter .
x-sign-jws-attached = x-sign-jws-split[0] + '.' + base64Url(HTTPRequest.Body) + '.' + x-sign-jws-split[1]
Now you can verify x-sign-jws-attached as shown below;
$decoded = JWT::decode($x-sign-jws-attached, $secret_key, array('JWT','HS256'));```

Prevent URL-encoding of values when adding headers to TRESTClient

I'm working on a Delphi REST client for a public API that requires an HMAC256/Base64 signed string to be added to the headers of the request to authenticate. I've spent hours trying to figure out why it's not working, so I compared the raw request from my Delphi client to that of a working C# library (using Wireshark).
It turns out my request matches perfectly the request generated by the working C# library, except that Delphi's REST client is URL-encoding the values added to the request's header, therefore invalidating the carefully crafted signature.
This is how I'm adding the signature string to the header:
RESTRequest1.Params.AddHeader('SIGNATURE', FSignature);
The signature string may have slashes, plus signs, and/or equal signs that are being URL-encoded when they shouldn't. For example when the value of the signature string is...
FSignature = '8A1BgACL9kB6P/kXuPdm99s05whfkrOUnEziEtU+0OY=';
...then the request should should output raw headers like...
GET /resource HTTP/1.1
User-Agent: Embarcadero URI Client/1.0
Connection: Keep-Alive
<snip>
SIGNATURE: 8A1BgACL9kB6P/kXuPdm99s05whfkrOUnEziEtU+0OY=
<snip>
...but instead Wireshark shows this as the real value being sent...
SIGNATURE: 8A1BgACL9kB6P%2FkXuPdm99s05whfkrOUnEziEtU%2B0OY%3D
Is there a way to prevent the URL-encoding of values when using AddHeader? Or maybe another way to add raw headers to a TRESTClient request?
PS: I already tried both TRESTRequest.Params.AddHeader and TRESTClient.AddParameter with TRESTRequestParameterKind.pkHTTPHEADER as the Kind parameter. Both resulted in URL-encoded values.
PS2: Using Delphi RAD Studio 10.3.
You should include poDoNotEncode in the Options property of the TRESTRequestParameter.
This can be done using:
RESTClient1.AddParameter('SIGNATURE', FSignature, pkHTTPHEADER, [poDoNotEncode]);
or by using:
RESTClient1.Params.AddHeader('SIGNATURE', FSignature).Options := [poDoNotEncode];

How to handle error responses in a REST endpoint that accepts different Accept header values.

I'm trying to add a new content type to a REST endpoint. Currently it only returns json but I now need to be able to return also a CSV file.
As far as I know, the best way to do this is by using the Accept header with value text/csv and then add a converter that is able to react to this and convert the returned body to the proper CSV representation.
I've been able to do this but then I have a problem handling exceptions. Up until know, all the errors returned are in json. The frontend expects any 500 status code to contain a specific body with the error. But now, by adding the option to return either application/json or text/csv to my endpoint, in case of an error, the converter to be used to transform the body is going to be either the jackson converter or my custom one depending on the Accept header passed. Moreover, my frontend is going to need to read the content-type returned and parse the value based on the type of representation returned.
Is this the normal approach to handle this situation?
A faster workaround would be to forget about the Accept header and include a url parameter indicating the format expected. Doing it this way, I'd be able to change the content-type of the response and the parsing of the data directly in the controller as the GET request won't include any Accept header and it will be able to accept anything. There are some parts of the code already doing this where the only expected response format is CSV so I'm going to have a difficult time defending the use of the Accept header unless there is a better way of handling this.
my frontend is going to need to read the content-type returned and parse the value based on the type of representation returned.
Is this the normal approach to handle this situation?
Yes.
For example, RFC 7807 describes a common format for describing problems. So the server would send an application/problem+json or an application/problem+xml representation of the issue in the response, along with the usual meta data in the headers.
Consumers that understand application/problem+json can parse the data with in, and forward a useful description of the problem to the user/logs whatever. Consumers that don't understand that representation are limited to acting on the information in the headers.
A faster workaround would be to forget about the Accept header and include a url parameter indicating the format expected.
That's also fine -- more precisely, you can have a different resource responsible for the each of the different media-types that you support.
It may be useful to review section 3.4 of RFC 7231, which describes the semantics of content negotiation.

HTTP "date" header is missing in UnityWebRequest

I am working with Unity3d and am trying to send a GET request to an API that requires the Date request header.
However UnityWebRequest does not send it automatically (I have checked with https://requestb.in/) and I cannot set it manually since "date" is one of the protected headers.
UnityWebRequest www = UnityWebRequest.Get (fullURL);
www.SetRequestHeader("Date", dateTimeString);
yield return www.Send();
and I get the following error:
ArgumentException: Cannot set Request Header Date - name contains illegal characters or is not user-overridable
I am able to communicate with the API successfully if I use the WWW class (which does allow me to set the "date" header manually) but am trying to do the same with the UnityWebRequest since WWW will be deprecated soon.
I tried to use System.Reflection's "InternalSetRequestHeader" (as implemented in https://forum.unity3d.com/threads/unitywebrequest-cookies.383530/#post-2621262) as follows:
System.Reflection.MethodInfo dynMethod = myReq.GetType ().GetMethod ("InternalSetRequestHeader", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
dynMethod.Invoke (myReq, new object[]{"Date", dateTimeString });
but then I get the following error:
InvalidOperationException: Cannot override system-specified headers
So, how can I make sure that the "date" request header is sent?
Is there a solution or do I have to use an object from a different library such as .NET's HttpWebRequest?
With UnityWebRequest you can't set custom values fro Date field, check docs.
Also, check RFC 2616, section 4.2, in particular RFC 2616, section 14.18 about Date header. Also, check RFC 2616 section 3.3.1.
Are you sure your dateTimeString is in correct format?

Extracting email attachment filename : Content-Disposition vs Content-type

I am working on a script that will handle email attachments. I see that, most of the time, both content-type and content-disposition headers have the filename, but I have seen cases where only one had proper encoding or valid mime header.
Is there a preferred header to use to extract the file name? If so, which one?
Quoting wikipedia http://en.wikipedia.org/wiki/MIME:
"Many mail user agents also send messages with the file name in the name parameter of the content-type header instead of the filename parameter of the content-disposition header. This practice is discouraged."
So it seems content-disposition is preferred. However as I am using JavaMail, current JavaMail API seems to have only a String getDisposition() method: http://javamail.kenai.com/nonav/javadocs/javax/mail/Part.html#getDisposition(). So you might need to work with the header directly if you are using JavaMail.