For a deeper look into our World Check One API, look into:

Overview |  Quickstart |  Documentation |  Downloads

question

Upvotes
Accepted
1 0 0 0

401 response only for POST requests

Hi,

We created a class in C# to place both GET and POST requests, but only GET requests are working.

For POST, we get a 401. So we are assuming that it's something to do with Authorization header.

I tried using the C# code example for POST requests, but the content of "World-Check One API C# .NET Request Code Examples" is for v1 and we are implementing v2. I even tried to just update v1 to v2 and we still get a 401 with this code example.

Can someone help me with that?

FYI, both GET and POST requests using Postman are working fine (returning 200).


world-checkworld-check-oneerror-401
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
Accepted
4.5k 4 7 8

@b.korte,

Thank you for the details.

I will send you an email shortly to schedule a call to investigate on the issue. Please revert back with a suitable time.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
4.5k 4 7 8

@b.korte,

Thank you for your query.

Could you please share the request and response headers of the GET request? Also for the PST request, please share the request and response headers with the request payload to investigate on the cause for error 401.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
1 0 0 0

The GET request parameters (which is working properly)


REQUEST

Parameters = {List<Parameter>} Count = 5
 [0] = {Parameter} "Accept=application/json"
 [1] = {Parameter} "Content-Type=application/json"
 [2] = {Parameter} "Date=Fri, 04 Sep 2020 12:59:42 GMT"
 [3] = {Parameter} "Authorization=Signature keyId="8123d1da-0093-43be-8742-e318048c0f8f",algorithm="hmac-sha256",headers="(request-target) host date",signature="Y7iU0HT9B6o2VLmfYDN9gm1iQpZWRYoUtJaUOHHisLA=""
 [4] = {Parameter} "Content-Length=0"

RESPONSE

Headers = {List<Parameter>} Count = 11
 [0] = {Parameter} "Strict-Transport-Security=max-age=15552000, includeSubdomains"
 [1] = {Parameter} "Cache-Control=no-store, must-revalidate, no-cache, max-age=0"
 [2] = {Parameter} "Pragma=no-cache"
 [3] = {Parameter} "X-XSS-Protection=1; mode=block"
 [4] = {Parameter} "X-Frame-Options=DENY"
 [5] = {Parameter} "X-Content-Type-Options=nosniff"
 [6] = {Parameter} "Date=Fri, 04 Sep 2020 12:59:47 GMT"
 [7] = {Parameter} "Transfer-Encoding=chunked"
 [8] = {Parameter} "Server="""
 [9] = {Parameter} "Expires=0"
 [10] = {Parameter} "Content-Type=application/json; charset=UTF-8"
Content = {"ABW":"Aruba","AFG":"Afghanistan","AGO":"Angola","AIA":"Anguilla","ALA":"Åland Islands",...}




The POST request (which is giving 401)


REQUEST

request = {RestSharp.RestRequest}
 AdvancedResponseWriter = {Action<Stream,IHttpResponse>} null
 AllowedDecompressionMethods = {DecompressionMethods[]} Count = 3
  [0] = {DecompressionMethods} None
  [1] = {DecompressionMethods} Deflate
  [2] = {DecompressionMethods} GZip
 AlwaysMultipartFormData = {bool} false
 Attempts = {int} 1
 Body = {RequestBody} null
 Credentials = {ICredentials} null
 DateFormat = {string} null
 Files = {List<FileParameter>} Count = 0
 JsonSerializer = {ISerializer} null
 Method = {Method} POST
 OnBeforeDeserialization = {System.Action<RestSharp.IRestResponse>}
 OnBeforeRequest = {System.Action<RestSharp.IHttp>}
 Parameters = {List<Parameter>} Count = 5
  [0] = {Parameter} "Accept=application/json"
  [1] = {Parameter} "Content-Type=application/json"
  [2] = {Parameter} "Date=Fri, 04 Sep 2020 13:53:35 GMT"
  [3] = {Parameter} "Authorization=Signature keyId="8123d1da-0093-43be-8742-e318048c0f8f",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length",signature="UaUHhxVN4vECwsH47s7Px+gqbYFr4mvpe5lnvaS3IGs=""
  [4] = {Parameter} "Content-Length=2"
  Raw View = {} 
 ReadWriteTimeout = {int} 0
 RequestFormat = {DataFormat} Json
 Resource = {string} "cases/summaries"
 ResponseWriter = {Action<Stream>} null
 RootElement = {string} null
 Timeout = {int} 0
 UseDefaultCredentials = {bool} false
 UserState = {object} null
 XmlNamespace = {string} null
 XmlSerializer = {IXmlSerializer} null


RESPONSE

response = {RestResponse} StatusCode: Unauthorized, Content-Type: , Content-Length: -1)
 Content = {string} ""
 ContentEncoding = {string} null
 ContentLength = {long} -1
 ContentType = {string} ""
 Cookies = {List<RestResponseCookie>} Count = 0
 ErrorException = {Exception} null
 ErrorMessage = {string} null
 Headers = {List<Parameter>} Count = 5
  [0] = {Parameter} "Strict-Transport-Security=max-age=15552000, includeSubdomains"
  [1] = {Parameter} "Authorization=WWW-Authenticate: Signature realm="World-Check One API",algorithm="hmac-sha256",headers="(request-target) host date content-type content-length""
  [2] = {Parameter} "Transfer-Encoding=chunked"
  [3] = {Parameter} "Date=Fri, 04 Sep 2020 13:53:39 GMT"
  [4] = {Parameter} "Server="""
  Raw View = {} 
 IsSuccessful = {bool} false
 ProtocolVersion = {Version} "1.1"
 RawBytes = {byte[]} Count = 0
 Request = {RestSharp.RestRequest}
 ResponseStatus = {ResponseStatus} Completed
 ResponseUri = {Uri} "https://rms-world-check-one-api-pilot.thomsonreuters.com/v2/cases/summaries"
 Server = {string} """"
 StatusCode = {HttpStatusCode} Unauthorized
 StatusDescription = {string} "" 

And this is the piece of code that build the parameters:


private static void GenerateCommonHeaders(IRestRequest request)
{
    var date = DateTime.UtcNow.ToString("R");

    var gatewayHost = "rms-world-check-one-api-pilot.thomsonreuters.com";
    var method = request.Method.ToString().ToLower();
    var path = "/v2/" + request.Resource;
    var dataToSign = $"(request-target): {method} " + path + "\n" +
                     "host: " + gatewayHost + "\n" +
                     "date: " + date;
    var headersList = "(request-target) host date";

    var contentLength = 0;

    var body = request.Parameters.Where(p => p.Type == ParameterType.RequestBody);
    if (request.Method == Method.POST)
    {
        var postData = JsonConvert.SerializeObject(body);
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] byte1 = encoding.GetBytes(postData);

        var contentType = "application/json"; //TODO: Extract this programatically from headers or request
        contentLength = byte1.Length;
        dataToSign = $"(request-target): {method} " + path + "\n" +
                     "host: " + gatewayHost + "\n" +   // no https only the host name
                     "date: " + date + "\n" +          // GMT date as a string
                     "content-type: " + contentType + "\n" +
                     "content-length: " + byte1.Length + "\n" +
                     postData;
        headersList += " content-type content-length";
    }

    var hmac = GenerateHMAC(dataToSign, <ApiSecret>);

    var authorization = $"Signature keyId=\"{<ApiKey>}\",algorithm=\"hmac-sha256\",headers=\"{headersList}\",signature=\"{hmac}\"";

    request.AddHeader("Date", date);
    request.AddHeader("Authorization", authorization);
    request.AddHeader("Content-Length", contentLength.ToString());
}

private static string GenerateHMAC(string dataToSign, string secretKey)
{
    var encoding = new ASCIIEncoding();
    byte[] keyBytes = encoding.GetBytes(secretKey);
    byte[] messageBytes = encoding.GetBytes(dataToSign);
    using (var hashFunction = new System.Security.Cryptography.HMACSHA256(keyBytes))
    {
        byte[] hash = hashFunction.ComputeHash(messageBytes);
        return Convert.ToBase64String(hash);
    }
}


icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.