Hello everyone, I'm unable to delete a blob from Azure storage account using the REST Api and Shared Key authorization. I can download and upload blobs, but not delete them. I know I'm missing something simple, but I can't point to where the issue is. I used the same method shown in the code below to sign the request for download and upload and it works fine, so it is not the signing code, it should be something on the request header. This is a simplified version of my code:
namespace AzureRestDelete
{
class Program
{
static async Task Main(string[] args)
{
string AccountName = "Azure-Account-Name";
string azEndPoint = "blob.core.windows.net";
string AccountKey = "Azure-Storage-Shared-Key";
string ContainerName = "Container-Name";
string ApiVersion = "2023-11-03";
string sourceBlobName = "Folder1/Folder2/SamplePicture.png";
string utcDate = DateTime.UtcNow.ToString("R");
string blobUrl = $"https://{AccountName}.{azEndPoint}/{ContainerName}/{sourceBlobName}";
using (var request = new HttpRequestMessage(HttpMethod.Delete, blobUrl))
{
// Construct the authorization header
string canonicalizedHeaders = $"x-ms-date:{utcDate}\nx-ms-version:{ApiVersion}\nx-ms-delete-snapshots:include"; //nx-ms-lease-id:
string canonicalizedResource = $"/{AccountName}/{ContainerName}/{sourceBlobName}";
string stringToSign = $"DELETE\n\n\n\n\n\n\n\n\n\n\n\n{canonicalizedHeaders}\n{canonicalizedResource}";
string authorizationHeader = SignThis(stringToSign, AccountKey, AccountName);
//Add headers
request.Headers.Add("x-ms-date", utcDate);
request.Headers.Add("x-ms-version", $"{ApiVersion}");
request.Headers.Add("x-ms-delete-snapshots", "include");
request.Headers.Add("Authorization", authorizationHeader);
HttpResponseMessage response = await new HttpClient().SendAsync(request);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Blob deleted");
}
else
Console.WriteLine("Failed:{0}", response.ToString());
}
Console.ReadKey();
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(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",
Account,
signature);
return authorizationHeader;
}
}
}
This the request, values have been replaced for security.
{Method: DELETE, RequestUri: 'https://myAzAccount.blob.core.windows.net/containerName/Folder1/Folder2/SamplePicture.png', Version: 1.1, Content: <null>, Headers:
{
x-ms-date: Mon, 04 Mar 2024 16:57:38 GMT
x-ms-version: 2023-11-03
x-ms-delete-snapshots: include
Authorization: SharedKey AccountName:67890abcdefghijkl1234567890ghjklopqwervhklT=
}}
This is the response:
{StatusCode: 403, ReasonPhrase: 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
x-ms-request-id: cdfaca5f-001e-002e-1455-6eb2ae000000
x-ms-error-code: AuthenticationFailed
Date: Mon, 04 Mar 2024 16:57:41 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 732
Content-Type: application/xml
}}
I noticed the Content is <null> on the request, according to this there is no need for it, and adding it to the header causes an error. What am I missing? Anyone?
Thank you.