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).


Best Answer

  • @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.

Answers

  • @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.

  • 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);
        }
    }


  • @b.korte,

    Please confirm if you were able to fix the issue with your code post our call.