Home > OS >  Error 403- When trying to retrieve single entity from Azure Table Storage using IHttpClientFactory
Error 403- When trying to retrieve single entity from Azure Table Storage using IHttpClientFactory

Time:07-21

Here department is PartitionKey and id is RowKey.

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

Status Code: Forbidden

If someone could help me to resolve this error It would be great.

Thanks in advance :)

public HttpClient getRequestHeaders(string requestType, HttpClient Newrequest, string storageAccount, string accessKey, string resource, int Length = 0)
        {
            HttpClient Client = Newrequest;
            
            var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
            if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
                Client.DefaultRequestHeaders.Remove("x-ms-date");
            Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
            
            var requestUri = @"https://"   storageAccount   ".table.core.windows.net/"   resource;

            Client.DefaultRequestHeaders.Accept.Clear();
            Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
                Client.DefaultRequestHeaders.Remove("x-ms-version");

            Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");

            if (Client.DefaultRequestHeaders.Contains("DataServiceVersion"))
                Client.DefaultRequestHeaders.Remove("DataServiceVersion");
            Client.DefaultRequestHeaders.Add("DataServiceVersion", "3.0;NetFx");

            if (Client.DefaultRequestHeaders.Contains("MaxDataServiceVersion"))
                Client.DefaultRequestHeaders.Remove("MaxDataServiceVersion");
            Client.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0;NetFx");


            if (Client.DefaultRequestHeaders.Contains("Authorization"))
                Client.DefaultRequestHeaders.Remove("Authorization");
            var sas =  getAuthToken(Client, storageAccount, accessKey, resource);
            Client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);

            return Client;
        }
        
        public string getAuthToken(HttpClient request, string storageAccount, string accessKey, string resource)
        {
            try
            {
                string sAuthTokn = "";

                string stringToSign = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture)   "\n";

                stringToSign  = "/"   storageAccount   "/"   resource;

                HMACSHA256 hasher = new HMACSHA256(Convert.FromBase64String(accessKey));

                sAuthTokn = "SharedKeyLite "   storageAccount   ":"   Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

                return sAuthTokn;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<string> GetEntityByID(string department, string id)
        {
            EmployeeDetails emp = new EmployeeDetails();
            string storageAccount = "sample";
            string resourcePath = "SampleAzureTableStorage";
            string accessKey = "<sample>";
            string uri = @"https://"   storageAccount   ".table.core.windows.net/"   resourcePath   "/";
            var request = _httpClientFactory.CreateClient();
            request = getRequestHeaders("GET", request, storageAccount, accessKey, resourcePath);
            
            try
            {
                var httpResponseMessage = await request.GetAsync(uri   department   "/"   id);
                httpResponseMessage.EnsureSuccessStatusCode();
                return await httpResponseMessage.Content.ReadAsStringAsync();
                
            }
            catch (WebException ex)
            {
                throw ex;
            }
        }

CodePudding user response:

I think the problem is in your Authorization header.

Here is your code:

Client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);

I think you should change it to:

Client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {sas}");

Otherwise the code looks righteous.

CodePudding user response:

I believe the reason you are getting this error is because you are using two different dates in your code.

You are getting the current date in getRequestHeaders method and then a different date in getAuthToken. This would cause the authorization header mismatch.

I would recommend modifying getAuthToken method and pass the date/time value computed in getRequestHeaders method.

Try the following code:

    public HttpClient getRequestHeaders(string requestType, HttpClient Newrequest, string storageAccount, string accessKey, string resource, string partitionKey, string rowKey, int Length = 0)
    {
        HttpClient Client = Newrequest;
        
        var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
        if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
            Client.DefaultRequestHeaders.Remove("x-ms-date");
        Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
        
        var requestUri = @"https://"   storageAccount   ".table.core.windows.net/"   resource;

        Client.DefaultRequestHeaders.Accept.Clear();
        Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
            Client.DefaultRequestHeaders.Remove("x-ms-version");

        Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");

        if (Client.DefaultRequestHeaders.Contains("DataServiceVersion"))
            Client.DefaultRequestHeaders.Remove("DataServiceVersion");
        Client.DefaultRequestHeaders.Add("DataServiceVersion", "3.0;NetFx");

        if (Client.DefaultRequestHeaders.Contains("MaxDataServiceVersion"))
            Client.DefaultRequestHeaders.Remove("MaxDataServiceVersion");
        Client.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0;NetFx");


        if (Client.DefaultRequestHeaders.Contains("Authorization"))
            Client.DefaultRequestHeaders.Remove("Authorization");
        var sas =  getAuthToken(Client, storageAccount, accessKey, resource, RequestDateString, partitionKey, rowKey);
        Client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);

        return Client;
    }
            
public string getAuthToken(HttpClient request, string storageAccount, string accessKey, string resource, string requestDateString, string partitionKey, string rowKey)
{
    try
    {
        string sAuthTokn = "";

        string stringToSign = requestDateString   "\n";

        stringToSign  = "/"   storageAccount   "/"   resource    "(PartitionKey='"   partitionKey   "',RowKey='"   rowKey   "')";

        HMACSHA256 hasher = new HMACSHA256(Convert.FromBase64String(accessKey));

        sAuthTokn = "SharedKeyLite "   storageAccount   ":"   Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

        return sAuthTokn;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

public async Task<string> GetEntityByID(string department, string id)
{
    EmployeeDetails emp = new EmployeeDetails();
    string storageAccount = "sample";
    string resourcePath = "SampleAzureTableStorage";
    string accessKey = "<sample>";
    string uri = @"https://"   storageAccount   ".table.core.windows.net/"   resourcePath   "/";
    var request = _httpClientFactory.CreateClient();
    request = getRequestHeaders("GET", request, storageAccount, accessKey, resourcePath, department, id);
    
    try
    {
        var httpResponseMessage = await request.GetAsync(uri   "(PartitionKey='"   department   "',RowKey='"   id   "')");
        httpResponseMessage.EnsureSuccessStatusCode();
        return await httpResponseMessage.Content.ReadAsStringAsync();
        
    }
    catch (WebException ex)
    {
        throw ex;
    }
}
  • Related