Search code examples
javascriptazurerestazure-table-storage

Azure Table REST API - Make sure the value of Authorization header is formed correctly including the signature


I'm currently trying to set up my static web app to get/post data to my Azure Table using Vanilla Javascript. I'm trying to test the REST API using POSTMAN with a simple GET request. However, I'm an error:

The server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.

Here is my code:

    var date = new Date();
    var utcDate = date.toUTCString();
    CanonicalizedResource = "" + "/" + "accountname/" + 'Tables';
    ContentMD5 = "";
    ContentType = ""; //Should this be empty? I've tried application/json as well as text/plain
    StringToSign = "GET" + "\n" +
                    ContentMD5 + "\n" +
                    ContentType + "\n" + 
                    utcDate + "\n" +  
            CanonicalizedResource;  


    var hmac = computeHMACSHA256(StringToSign, 'key from Azure Table');
    console.log(StringToSign);
    console.log(utcDate);
    console.log(hmac);
function computeHMACSHA256(stringToSign, accountKey) {
    const key = Buffer.from(accountKey, "base64");
    return crypto.createHmac("sha256", key).update(stringToSign, "utf8").digest("base64");
} //this function is taken from the Javascript client service so that I could test.

In Postman, I have 4 headers in my GET request.

Authorization: SharedKey accountname:signature

Date: Date in GMT

x-ms-version: 2019-02-02

DataServiceVersion: 3.0;NetFx

I have read through the Azure documentation to create the signature, but still no luck. I've used the Azure Javascript client service to test the connection, and it works. For administrative purposes, I'd prefer to communicate with Tables using REST HTTP requests.

Unfortunately, I was unable to find anything through searching with this specific setup. I've verified it works using SharedKeyLite (through the client service). I'm thinking something is wrong with my StringToSign, but still unsure.

Hoping someone can see what's wrong here.


Solution

  • It looks like you're attempting to manually generate the Shared Key Lite authentication for an Azure Table Storage request. The issue could be related to the way you're constructing the StringToSign and the Authorization header.

    Here's an alternative version of your code with some explanations:

    const crypto = require('crypto');
    
    // Function to compute HMAC-SHA256
    function computeHMACSHA256(stringToSign, accountKey) {
        const key = Buffer.from(accountKey, "base64");
        return crypto.createHmac("sha256", key).update(stringToSign, "utf8").digest("base64");
    }
    
    // Construct the request headers
    const date = new Date().toUTCString();
    const canonicalizedResource = "/" + "accountname/" + 'Tables';
    const contentMD5 = "";
    const contentType = "";  // Use application/json if you're sending JSON data
    const stringToSign = `GET\n${contentMD5}\n${contentType}\n${date}\n${canonicalizedResource}`;
    
    // Replace 'key from Azure Table' with your actual account key
    const signature = computeHMACSHA256(stringToSign, 'key from Azure Table');
    
    // Construct the Authorization header
    const authorizationHeader = `SharedKey accountname:${signature}`;
    
    console.log("StringToSign:", stringToSign);
    console.log("Date:", date);
    console.log("Authorization Header:", authorizationHeader);
    

    Note: Make sure to replace 'key from Azure Table' with your actual Azure Table Storage account key.

    Additionally, when constructing the StringToSign, ensure that the CanonicalizedResource includes the specific table name you're interacting with.

    For example, if your table is named 'MyTable', the CanonicalizedResource should be "/accountname/Tables/MyTable".