Hi there,
Currently I am trying to integrate your API to our system.
I keep getting the same error 401 from my code. Postman works though.
I use fillder to catch the request send by postman and visual studio. For the authorization part they looks exactly the same except the hashed part.
POST /v1/cases/screeningRequest HTTP/1.1 Date: Thu, 23 May 2019 17:30:21 GMT Content-Type: application/json Authorization: Signature keyId="x",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length",signature="jMx3FJvGsR2A2Q23fk90ihCwou3u00LHFwejYoxa1+o=" Content-Length: 150 User-Agent: PostmanRuntime/7.13.0 Accept: */* Cache-Control: no-cache Postman-Token: 736fcfdd-3fd7-45d1-93fc-b74bdfb55552 Host: zfs-world-check-one-api-pilot.thomsonreuters.com accept-encoding: gzip, deflate Connection: close POST /v1/cases/screeningRequest HTTP/1.1 Date: Thu, 23 May 2019 17:37:29 GMT Authorization: Signature keyId="x",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length",signature="6jslfdOjpdkwdjbc7CdjE1QMQig30Tmu4TFUmS3j/CE=" Accept: */* Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Host: zfs-world-check-one-api-pilot.thomsonreuters.com Content-Length: 150 Expect: 100-continue Connection: Keep-Alive
I also tried to hard code the time to match the one send by postman, then I got exactly the same hashed value. So I suppose the hash function is ok as well?
If so, why I keep getting 401 error? Can you help me to take a look my code? Thanks
public async Task<WorldCheckOneClientResponse> VerifyAsync(WorldCheckOneClientRequest request, CancellationToken cancellationToken) { var currentDate = DateTime.UtcNow; var requestToSent = "{\"groupId\":\"xxxxxxxxxxxxxxxx\",\"entityType\": \"INDIVIDUAL\",\"providerTypes\": [\"WATCHLIST\"],\"name\": \"john smith\",\"secondaryFields\":[]}"; UTF8Encoding encoding = new UTF8Encoding(); var contentLength = encoding.GetBytes(requestToSent).Length; using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, request.EndpointUrl)) { using (var stringContent = new StringContent(requestToSent, Encoding.UTF8, "application/json")) { httpRequest.Headers.Date = currentDate; httpRequest.Content = stringContent; httpRequest.Headers.Add("Authorization", getAuthorizationHeader(getDataToSign(request.EndpointUrl, currentDate, contentLength), request.ApiSecret, request.ApiKey)); httpRequest.Headers.Add("Accept","*/*"); httpRequest.Headers.Add("Cache-Control", "no-cache"); using (var response = await _httpClient.SendAsync(httpRequest, cancellationToken)) { var clientResponse = await response.Content.ReadAsStringAsync(); OnResponseReceived(clientResponse); if (response.IsSuccessStatusCode) { return JsonConvert.DeserializeObject<WorldCheckOneClientResponse>(clientResponse); } return new WorldCheckOneClientResponse { HasError = true, ErrorCode = response.StatusCode, }; } } } } private string getDataToSign(Uri endpointUri, DateTime dateTime, int contentLength) { var dataToSign = "(request-target): post " + "/v1/" + "cases/screeningRequest\n" + "host: " + endpointUri.Host + "\n" + "date: " + dateTime.ToString("R") + "\n" + "content-type: " + "application/json" +"\n" + "content-length: " + contentLength; return dataToSign; } private string getAuthorizationHeader(string message, string secret, string apiKey) { secret = secret ?? ""; var encoding = new System.Text.ASCIIEncoding(); byte[] keyByte = encoding.GetBytes(secret); byte[] messageBytes = encoding.GetBytes(message); using (var hmacsha256 = new HMACSHA256(keyByte)) { var hashmessage = hmacsha256.ComputeHash(messageBytes); var hmc = Convert.ToBase64String(hashmessage); var returnValue = "Signature keyId=\"" + apiKey + "\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"" + hmc + "\""; return returnValue; } }