I'm trying to create a Blob Container using C# and the REST API (in Xamarin.Android). I'm able to upload a blob to an existing container, but I can't seem to create a container via REST. The error is (403) Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. Creating the Authorization Header works when uploading a blob, so it must be something with the way I'm constructing the container's string to be signed, but for the life of me I can't find the problem. Here's the code:
private async Task<bool> CreateContainer(string containerName)
{
String requestMethod = "PUT";
String msVersion = "2009-09-19";
string dt = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dt, msVersion);
String canonicalizedResource = String.Format("/{0}/{1}\nrestype:container", AzureStorageConstants.Account, containerName);
String stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
string auth = SignThis(stringToSign);
string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container", AzureStorageConstants.Account, containerName);
Uri uri = new Uri(urlPath);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", dt);
client.DefaultRequestHeaders.Add("x-ms-version", "2009-09-19");
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpContent empty = null;
HttpResponseMessage response = await client.PutAsync(uri, empty);
return response.IsSuccessStatusCode;
}
private static String SignThis(String StringToSign)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(AzureStorageConstants.Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
AzureStorageConstants.Account,
signature);
return authorizationHeader;
}