401 Unauthorized error when using C# HttpClient
Hi.
I get an 401 unauthorized error when trying to execute a POST request to the World Check API. I can successfully execute the POST request using Postman. Any help would be appreciated.
My code is as follows:
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace World_CheckAPITester
{
using System = global::System;
class Program
{
static async Task Main(string[] args)
{
await new Program().UsingHttpClient();
}
// Combine the data signature and the API secret key to get the HMAC
// This is the Microsoft HMACSHA256 code copied from the documentation
private 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);
string hex = BitConverter.ToString(rawHmac).Replace("-", "");
return (Convert.ToBase64String(rawHmac));
}
private async Task UsingHttpClient() {
try
{
HttpClient wc1Client = new HttpClient();
string apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string apiSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string groupId = "0a3687cf-6c70-198a-9b22-d3fa000009bb";
string wc1Protocol = "https://";
string wc1Gatewayhost = "rms-world-check-one-api-pilot.thomsonreuters.com";
string wc1GatewayUrl = "/v1/";
string wc1QueryUrl = "cases/screeningRequest";
string wc1Date = DateTime.UtcNow.ToString("R");
dynamic postObject = new ExpandoObject();
postObject.secondaryFields = new string[] { };
postObject.entityType = "INDIVIDUAL";
postObject.customFields = new string[] { };
postObject.groupId = groupId;
postObject.providerTypes = new string[] { "WATCHLIST" };
postObject.name = "john smith";
string postData = JsonConvert.SerializeObject(postObject);
UTF8Encoding encoding = new UTF8Encoding();
byte[] byte1 = encoding.GetBytes(postData);
string dataToSign = "(request-target): post " + wc1GatewayUrl + "cases/screeningRequest\n" +
"host: " + wc1Gatewayhost + "\n" + // no https only the host name
"date: " + wc1Date + "\n" + // GMT date as a string
"content-type: " + "application/json" + "\n" +
"content-length: " + byte1.Length + "\n" +
postData;
string hmac = generateAuthHeader(dataToSign, apiSecret);
string authorisation = "Signature keyId=\"" + apiKey + "\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"" + hmac + "\"";
wc1Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
wc1Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", authorisation);
wc1Client.DefaultRequestHeaders.Date = DateTime.UtcNow;
StringContent postContent = new StringContent(JsonConvert.SerializeObject(postObject), Encoding.UTF8, "application/json");
HttpResponseMessage httpResponse = await wc1Client.PostAsync(wc1Protocol + wc1Gatewayhost + wc1GatewayUrl + "cases/screeningRequest", postContent);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
}
}
}
}
Regards.
Best Answer
-
Thank you for sharing the details.
Firstly, I see that there is a difference of more than 30 seconds between request date and response date timestamp in the headers. The time difference of 30 seconds is acceptable for a successful API call. Can you please adjust the system time to NTP and they re-try?
Secondly, In a POST request the headers would be -
1. Date
2. Authorization
3. Content Length
4. Content Type
From the above headers, it looks like only Date and Authorisation is passed as the request headers. Could you please add the content length and the content type as well in the request headers and then try again?
Please provide us the updated request and response headers along with the request body if you are still getting Error 401 after making the above suggested changes to assist you further.
0
Answers
-
Thank you for your query.
Can you please provide us the request headers and the response headers along with the request body of the failed API call to investigate on the cause of Error 401?
0 -
The request and the response headers as well as the request body generated by sample code I posted are as follows:
Request headers:
Accept: application/json
Authorization: basic Signature keyId="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length",signature="CZZr0aVS0jSJTUH2cUd3aKhoLZPN6wT9cBV/QeA45aY="
Date: Tue, 05 Nov 2019 08:47:34 GMTRequest Body:
{
"secondaryFields": [],
"entityType": "INDIVIDUAL",
"customFields": [],
"groupId": "0a3687cf-6c70-198a-9b22-d3fa000009bb",
"providerTypes": [
"WATCHLIST"
],
"name": "john smith"
}Response Headers:
X-Application-Context: application
Authorization: WWW-Authenticate: Signature realm="World-Check One API",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length
Transfer-Encoding: chunked
Date: Tue, 05 Nov 2019 08:50:02 GMT
Server: ""I suspect that the request headers are incorrect which is why I need some guidance on how to set the request headers on a C# HttpClient object
Regards0 -
You said:
"Firstly, I see that there is a difference of more than 30 seconds between request date and response date timestamp in the headers. The time difference of 30 seconds is acceptable for a successful API call. Can you please adjust the system time to NTP and they re-try?"
That I can explain, I have set a breakpoint in my code after creating the Httpclient object where the code execution was paused while I copied the header values, which explains the time difference. Apologies for any confusion that might have caused.
Also, I understand that the Date, Authorization, Content Length and Content Type headers are required, but I'm struggling to set them correctly in my code. Can you please provide a sample of C# code on how to set the request headers on a C# HttpClient object?
Regards.0 -
I'm afraid, we do not have sample C# code for HttpClient object.
0
Categories
- All Categories
- 6 AHS
- 39 Alpha
- 161 App Studio
- 4 Block Chain
- 4 Bot Platform
- 16 Connected Risk APIs
- 47 Data Fusion
- 30 Data Model Discovery
- 608 Datastream
- 1.3K DSS
- 577 Eikon COM
- 4.9K Eikon Data APIs
- 7 Electronic Trading
- Generic FIX
- 7 Local Bank Node API
- Trading API
- 2.7K Elektron
- 1.3K EMA
- 236 ETA
- 519 WebSocket API
- 33 FX Venues
- 10 FX Market Data
- 1 FX Post Trade
- 1 FX Trading - Matching
- 12 FX Trading – RFQ Maker
- 5 Intelligent Tagging
- 2 Legal One
- 20 Messenger Bot
- 2 Messenger Side by Side
- 9 ONESOURCE
- 7 Indirect Tax
- 59 Open Calais
- 264 Open PermID
- 39 Entity Search
- 2 Org ID
- PAM
- PAM - Logging
- 8.4K Private Comments
- 6 Product Insight
- Project Tracking
- ProView
- ProView Internal
- 20 RDMS
- 1.4K Refinitiv Data Platform
- 367 Refinitiv Data Platform Libraries
- 3 Refinitiv Due Diligence
- LSEG Due Diligence Portal API
- 3 Refinitiv Due Dilligence Centre
- Rose's Space
- 1.1K Screening
- 18 Qual-ID API
- 13 Screening Deployed
- 23 Screening Online
- 10 World-Check Customer Risk Screener
- 990 World-Check One
- 44 World-Check One Zero Footprint
- 45 Side by Side Integration API
- Test Space
- 3 Thomson One Smart
- 1.2K TR Internal
- Global Hackathon 2015
- 2 Specialists Who Code
- 10 TR Knowledge Graph
- 150 Transactions
- 142 REDI API
- 1.7K TREP APIs
- 4 CAT
- 21 DACS Station
- 117 Open DACS
- 1.1K RFA
- 103 UPA
- 172 TREP Infrastructure
- 224 TRKD
- 886 TRTH
- 5 Velocity Analytics
- 5 Wealth Management Web Services
- 59 Workspace SDK
- 9 Element Framework
- 5 Grid
- 13 World-Check Data File
- Yield Book Analytics
- 46 中文论坛