0

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?

1
  • Can you please try with the following: var stringToSign = $"GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:{requestDate}\nx-ms-version:2023-08-03\n{canonicalizedResource}";. I added x-ms-date: to your stringToSign. Commented Apr 15, 2024 at 11:41

1 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

1 Comment

It seems that the problem was caused by the string interpolation on a single line, in addition to the header x-ms-date not being correctly added. Modifying the way stringToSign is constructed has worked. Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.