Post requests not working with C# HttpClient

We are trying to integrate WorldCheck one API using C# HttpClient in out .Net core application. We always receive 401 UnAuthorized response when sending Post requests using C# HttpClient in out .Net Core application.

Same request payload and authorization signature works well with HttpWebRequest object which we can make sure that there is no issue with generating the authorisation header. HttpWebRequest object is obsolete in modern .Net core versions and static code analysing tools also complaining about it. Get requests are working fine with C# HttpClient. All the C# sample code available in this forum were written in HttpWebRequest which we cannot use for our implementation. Do you have working sample C# code using HttpClient instead of HttpWebRequest?


Here is the sample code using C# HttpClient.

public void SendRequestWithHttpClient()
{
DateTime dateValue = DateTime.UtcNow;

string date = dateValue.ToString("R");

string apikey = "cf9c27ef-32ab-412a-XXXXXXXXXXXXXXXXXXX";
string apisecret = "2my_api_secret";
string gatewayurl = "/v2/";
string gatewayhost = "api-worldcheck.refinitiv.com";

string postData = Newtonsoft.Json.JsonConvert.SerializeObject(GenerateRequest());

string msg = postData;
UTF8Encoding encoding = new UTF8Encoding();
byte[] byte1 = encoding.GetBytes(postData);


string dataToSign = "(request-target): post " + gatewayurl + "cases/screeningRequest\n" +
"host: " + gatewayhost + "\n" + // no https only the host name
"date: " + date + "\n" + // GMT date as a string
"content-type: " + "application/json" + "\n" +
"content-length: " + byte1.Length + "\n" +
msg;

string hmac = generateAuthHeader(dataToSign, apisecret);


string authorisation = "Signature keyId=\"" + apikey + "\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"" + hmac + "\"";


using var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://api-worldcheck.refinitiv.com");
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("Authorization", authorisation);
httpClient.DefaultRequestHeaders.Add("Date", date);
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Date = dateValue;
//httpClient.DefaultRequestHeaders.Add("Content-Type", "appplication/json");
//httpClient.DefaultRequestHeaders.Add("Content-Length", byte1.Length.ToString());


var response = httpClient.PostAsync("/v2/cases/screeningRequest", new StringContent(postData,Encoding.UTF8, "application/json")).Result;


if (response.IsSuccessStatusCode)
{
var responseText = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseText);
}
}

public static string generateAuthHeader(string dataToSign, string apisecret)
{
byte[] secretKey = Encoding.UTF8.GetBytes(apisecret);
HMACSHA256 hmac = new HMACSHA256(secretKey);
hmac.Initialize();

byte[] bytes = Encoding.UTF8.GetBytes(dataToSign);
byte[] rawHmac = hmac.ComputeHash(bytes);
Console.WriteLine("---rawHmac---");
string hex = BitConverter.ToString(rawHmac).Replace("-", "");
Console.WriteLine(hex);
return (Convert.ToBase64String(rawHmac));
}

Best Answer

Answers

  • Thanks Vivek for the prompt response,


    As mentioned in the given sample code, Content-Type and Content-Length need to be passed inside the content headers. We were passing it in the request headers. Now it's working. Thanks