I have been working on a proof of concept and looking to test against the Azure Storage REST API. However, I cannot authenticate. I have tried all day with reading and tweaking and rewriting and it still does not work. I have been through the documentation step by step.
I am hoping to find someone who has managed this. Lots of hard coded bits, it is just to get it working. I keep getting this error back in response
The MAC signature found in the HTTP request '' is not the same as any computed signature
Can anyone see what is maybe staring me in the face? It's driving me mad.
var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var StorageAccountName = "<account removed>";
var StorageKey = "<key removed>";
using (var client = new HttpClient())
{
var stringToSign = new List<string>(){
"GET" /*HTTP Verb*/
,"" /*Content-Encoding*/
,"" /*Content-Language*/
,"" /*Content-Length (include value when zero)*/
,"" /*Content-MD5*/
,"" /*Content-Type*/
,"" /*Date*/
,"" /*If-Modified-Since */
,"" /*If-Match*/
,"" /*If-None-Match*/
,"" /*If-Unmodified-Since*/
,"" /*Range*/
,$"x-ms-date:{requestDateString}\nx-ms-version:2015-02-21" /*CanonicalizedHeaders*/
,$"/{StorageAccountName}/ " + _containerName + "\ncomp:metadata\nrestype:container\ntimeout:20" /*CanonicalizedResource*/
};
string signature;
using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
var compiledStringToSign = (string.Join("\n", stringToSign));
byte[] dataToHmac = Encoding.UTF8.GetBytes(compiledStringToSign);
signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
}
//Send Request
client.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
client.DefaultRequestHeaders.Add("x-ms-version", " 2015-02-21");
client.DefaultRequestHeaders.Add("Authorization", $"SharedKey {StorageAccountName}:" + signature);
var response = client.SendAsync(request);
//edit The Request URL is https://account.blob.core.windows.net/testcontainer/blobtest/blob1234
The error is quite specific about failing authentication so I think the error must be in the signature, i really can't see it though. I checked all the outputs with fiddler to ensure they matched
If you want to get the blob content, please have a try to use the following demo code, it works correctly on my side.
var blobStorageAccount = "account name";
var storageKey = "account key";
var containerName = "container name";
var requestMethod = "GET";
var blobName = "blob name"; // in your case:blobtest/blob1234
var dt = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var msVersion = "2015-02-21";
var clientRequestId = Guid.NewGuid().ToString();
var canHeaders = $"x-ms-client-request-id:{clientRequestId}\nx-ms-date:{dt}\nx-ms-version:{msVersion}";
var canResource = $"/{blobStorageAccount}/{containerName}/{blobName}"; //not the CanonicalizedResource : /myaccount/mycontainer\ncomp:metadata\nrestype:container\ntimeout:20
var signStr = $"{requestMethod}\n\n\n\n\n\n\n\n\n\n\n\n{canHeaders}\n{canResource}";
var auth = CreateAuthString(blobStorageAccount, signStr, storageKey);
var urlPath = $"https://{blobStorageAccount}.blob.core.windows.net/{containerName}/{blobName}";
Uri uri = new Uri(urlPath);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", dt);
client.DefaultRequestHeaders.Add("x-ms-version", msVersion);
client.DefaultRequestHeaders.Add("x-ms-client-request-id", clientRequestId);
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpResponseMessage response = client.SendAsync(request).Result;
var status = response.IsSuccessStatusCode;
private static string CreateAuthString(string blobStorageAccount,string signStr,string blobStorageAccessKey)
{
var signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(blobStorageAccessKey);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(signStr);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
var authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
blobStorageAccount,
signature);
return authorizationHeader;
}