Search code examples
httpclientblazor-webassemblyazure-table-storageblazor-hybrid

Azure Tables HTTP Rest Authorization Header Inconsistent


I am using a HttpClient to make requests to Azure TableStorage. The code I am using to generate the authorisation header using SharedKeyLight method is:

    string stringToSign = string.Format("{0}\n/{1}/{2}",
            date,
            account,
            Table
        );

    var hasher = new HMACSHA256(sharedKey);

    string signedSignature = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    string authorizationHeader = string.Format("{0} {1}:{2}", "SharedKeyLite", account, signedSignature);

where date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture) and account is a string with the azure storage account name and table is a string with the table name.

This works fine as is for a POST method to https://[AzureURL]/[TableName]

[UPDATE] stringToSign for the POST methods which works is:

"Sun, 01 Jan 2023 16:52:15 GMT\n/[AccountName]/Benefits"

For a GET request to a url with a querystring (say) https://[AzureURL]/[TableName]()?$filter=(PartitionKey%20eq%20'QueryValue') I have to use the table name and ():

string stringToSign = string.Format("{0}\n/{1}/{2}",
        date,
        account,
        Table + "()"
    );

This makes some sense as the table is suffixed with () before the ? for the querystring to start.

[UPDATE] the stringToSign for the GET requests that works is:

"Sun, 01 Jan 2023 16:58:05 GMT\n/[AccountName]/Benefits()"

For DELETE and PUT methods to (say) https://[AzureURL]/[TableName](PartitionKey='{PartitionKeyValue}', RowKey='{RowKeyValue}') neither of these variants of the signature string seem to work and I get a response from Azure of

Forbidden - Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature

Any idea of what I might need to do to form an appropriate signature string for a DELETE or PUT request?


Solution

  • Based on the documentation provided here, you would need to use URL encoded path of the resource.


    enter image description here


    Please specify the canonical resource with the following while constructing the string to sign:

    /account/table(PartitionKey='{PartitionKeyValue}',%20RowKey='{RowKeyValue}')