azureauthorizationazure-rest-api

List Blobs using Azure API Rest returns Forbidden


I'm trying to get the list of blobs inside a folder using the Azure Rest API and I'm getting 403 Forbidden for a problem building the authorization signature for the Shared Key.

Here is my source code:

// Build the authorization signature
var requestDate = DateTime.UtcNow.ToString("R");
var canonicalizedResource = $"/{accountName}/{containerName} \ncomp:list\nprefix:contacts/{contactId}\nrestype:container";
var stringToSign = $"GET\n\n\n\n\n\n\n\n\n\n\n\n{requestDate}\nx-ms-version:2023-08-03\n{canonicalizedResource}";
string signature;
using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
{
    var dataToHmac = Encoding.UTF8.GetBytes(stringToSign);
    signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
}

// Make the HTTP GET request
var url = $"https://{accountName}.blob.core.windows.net/{containerName}?restype=container&comp=list&prefix=contacts/{contactId}";
using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Add("x-ms-version", "2023-08-03");
    client.DefaultRequestHeaders.Add("x-ms-date", requestDate);
    client.DefaultRequestHeaders.Add("Authorization", $"SharedKey {accountName}:{signature}");

    var response = await client.GetAsync(url);

    // Process the response
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        Console.WriteLine("List of blobs in the container:");
        Console.WriteLine(responseContent);
    }
    else
    {
        Console.WriteLine($"Error getting list of blobs. Status code: {response.StatusCode}");
    }
}

Am I missing something?


Solution

  • List Blobs using Azure API Rest returns Forbidden.

    I agree with Gaurav Mantri's comment. The above error occurs when you pass the wrong parameters in stringtosign in the code.

    Here is the modified code to list the blob in a particular folder from Azure Blob Storage:

    Code:

    using System.Security.Cryptography;
    using System.Text;
    using System.Xml.Linq;
    
    class Program
    {
        static async Task Main(string[] args)
        {
            var accountName = "venkat123";
            var containerName = "test";
            var contactId = "contacts/ContactId";
            var accessKey = "your access key";
            var apiversion = "2023-08-03";
    
            
            DateTime dt = DateTime.UtcNow;
            string StringToSign = String.Format("GET\n"
                + "\n" // content encoding
                + "\n" // content language
                + "\n" // content length
                + "\n" // content md5
                + "\n" // content type
                + "\n" // date
                + "\n" // if modified since
                + "\n" // if match
                + "\n" // if none match
                + "\n" // if unmodified since
                + "\n" // range
            + "x-ms-date:" + dt.ToString("R") + "\nx-ms-version:" + apiversion + "\n" // headers
                + "/{0}/{1}\ncomp:list\nprefix:{2}\nrestype:container", accountName, containerName,contactId);
            string signature;
            using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
            {
                var dataToHmac = Encoding.UTF8.GetBytes(StringToSign);
                signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
            }
    
            // Make the HTTP GET request
            var url = $"https://{accountName}.blob.core.windows.net/{containerName}?restype=container&comp=list&prefix={contactId}";
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("x-ms-version", "2023-08-03");
                client.DefaultRequestHeaders.Add("x-ms-date", dt.ToString("R"));
                client.DefaultRequestHeaders.Add("Authorization", $"SharedKey {accountName}:{signature}");
    
                var response = await client.GetAsync(url);
    
                // Process the response
                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();
                    var xmlDoc = XDocument.Parse(responseContent);
                    Console.WriteLine("List of blobs in the container:");
                    Console.WriteLine(xmlDoc.ToString(SaveOptions.None));
                }
                else
                {
                    Console.WriteLine($"Error getting list of blobs. Status code: {response.StatusCode}");
                }
            }
        }
    }
    

    Output:

    List of blobs in the container:
    <EnumerationResults ServiceEndpoint="https://venkat123.blob.core.windows.net/" ContainerName="test">
      <Prefix>ContactId</Prefix>
      <Blobs>
        ...
      </Blobs>
      <NextMarker />
    </EnumerationResults>
    

    Blobs in the container

    Reference: List Blobs (REST API) - Azure Storage | Microsoft Learn