question

Upvotes
Accepted
1 1 1 2

php curl response is blank

I am initiating the integration to World-Check One and right off the bat I am facing an issue with getting no response when I make a GET request through php cURL. I have followed the postman collection, and used the php cURL that was generated in there. Postman gives the response while my code doesn't. I have tested the base64_encode of hmac-sha256 as well and all are being generated as expected in the private functions of the class.

The last function is what I am calling for getting the list of groups.

Here is my code:

class ThomsonReutersHelper
{
    /**
     * Generate header signature
     *
     * @param $dataToSign
     * @return string
     */
    private function generateAuthHeader($dataToSign)
    {
        if(!($secret = config('app.tr_secret'))){
            Log::warning('[TR-generateAuthHeader] Missing app secret.');
            return forbiddenError('Missing TR Secret.');
        }
        try{
            return base64_encode(hash_hmac('sha256', $dataToSign, $secret));
        }
        catch (\Exception $e){
            Log::error('[TR-generateAuthHeader] failed.',[$e->getMessage()]);
            return serverError('Failed to generate auth header.');
        }
    }

    private function dataToSign($endpoint, $date)
    {
        if(!($url = config('app.tr_url'))){
            Log::warning('[TR-dataToSign] Missing TR url.');
            return forbiddenError('Missing URL.');
        }
        if(!($host = config('app.tr_host'))){
            Log::warning('[TR-dataToSign] Missing TR host.');
            return forbiddenError('Missing Host.');
        }

        return "(request-target): get " . $url . "$endpoint\n"."host: $host\n"."date: $date";
    }

    private function getHeaderData($endpoint)
    {
        if(!($key = config('app.tr_key'))){
            Log::warning('[TR-getHeaderData] Missing TR key.');
            return forbiddenError('Missing key.');
        }
        $date = gmdate('D, d M Y H:i:s').' GMT';
        $authorization = "Signature keyId=\"" . $key . "\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date\",signature=\"" . $this->generateAuthHeader($this->dataToSign($endpoint, $date)) . "\"";
        return [
            'authorization' => $authorization,
            'date' => $date
        ];
    }

    public function test(){
        $endpoint = 'groups';
        $headers = $this->getHeaderData($endpoint);
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => config('app.tr_host').config('app.tr_url').$endpoint,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_HTTPHEADER => array(
                "Authorization: ".$headers['authorization'],
                "Cache-Control: no-cache",
                "Content-Type: application/json",
                $headers['date']
            ),
        ));

        $response = curl_exec($curl);
        $errno = curl_errno($curl);
        $err = curl_error($curl);

        curl_close($curl);

        if ($errno) {
            return "cURL Error #:" . $err;
        } else {
            return $response;
        }
    }
}
world-checkworld-check-onephpresponse
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
1 1 1 2

Ok so the problem with generating the signature was:

  • Under generateAuthHeader function, forth parameter was required to be true ($hmac = hash_hmac('sha256', $dataToSign, $secret, true);)
  • The dataToSign() function should return in this format: return "(request-target): get $url$endpoint\nhost: $host\ndate: $date";
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.2k 8 5 6

Hello @Max Daneshvar ,

What is the response code you are receiving when you call the API?

Kindly compare the signature generated by your code and the one generated by Postman to see if they match. For this, execute your code and then use the same time stamp in Postman and send the API request (obviously the API would fail as the time stamp is incorrect but it would still generate the signature) to check the signature being generated by it.

You can check this in Postman by clicking the code just below "Save" button on the right side of Postman. Select the dropdown as PHP->curl. This will generate the entire code along with the entire code for that particular request.

You can use this to understand when you are going wrong.

I would need the response code to debug this further.

Please send me the output generated by your code in the below format so that I can look into this.

Request End Point: https://rms-world-check-one-api-pilot.thomsonreuters.com/v1/groups
GET(request-target): get/v1/groups
host: rms-world-check-one-api-pilot.thomsonreuters.com
date: Fri, 06 Apr 2018 06:21:40 GMT

Signature keyId="0b9f66af-044ea74bf97db",algorithm="hmac-sha256",headers="(request-target) host date",signature="JhBYaQc/fo0PK3KANaGmFPVBl+F0Mm5cyoR3z9i3ysw="

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.

Hi @Irfan.Khan,

Below is generated by my code:

Request End Point: https://rms-world-check-one-api-pilot.thomsonreuters.com/v1/groups

GET(request-target): get/v1/groups
host: rms-world-check-one-api-pilot.thomsonreuters.com
date: Tue, 24 Apr 2018 05:00:44 GMT

(Above format is modified to follow your guide, added GET in front, and a space from get /v1/groups)

Signature keyId=\"f8bd552a-f52d-4b3c-ad9e-eaf7038e99f7\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date\",signature=\"1flazxQiyyRlZgwIm9buzUedL2z7iekjDTf2BDwkMyU=\"

Status comes back as 200 with a blank page.

Hi @Max Daneshvar ,

I apologize to paste the wrong format for the dataToSign output.

Please find the correct one below:

(request-target): get /v1/groups

host: rms-world-check-one-api-pilot.thomsonreuters.com

date: Tue, 24 Apr 2018 05:00:44 GMT

There is a space after "get" in the line "(request-target): get /v1/groups".

Getting a 200 response for this is quite unusual as this should fail with a 401 unauthorized error.

I am using php cURL and it is suppose to either return the error or give me the response. I get blank response with status 200.

Regarding the format of dataToSign, I have tried this as well, and still was I see is a different signature as compared to postman even though I am copying the exact date value (as string) into my code and sending the date statically.

it is either I am getting the format wrong somehow or base64_encode(hash_hmac('sha256', $dataToSign, $secret, true)) in php doesn't do what the java code is doing in postman.

Upvotes
4.2k 8 5 6

Hello @Max Daneshvar ,

Just reviewed the code, please check the value of variable $url that you are using in the function dataTosign (). This function should return value in the below format:

GET(request-target): get/v1/groups
host: rms-world-check-one-api-pilot.thomsonreuters.com
date: Fri, 06 Apr 2018 06:21:40 GMT

Also, please check the below code of the function test(). It should pass headers to WC1 API which is acceptable by the system.

CURLOPT_HTTPHEADER => array(
"Authorization: ".$headers['authorization'],
"Cache-Control: no-cache",
"Content-Type: application/json",
$headers['date']
),

Please find the format below:

'Date': "Mon, 23 Apr 2018 11:20:00 GMT",
'Authorization': "Signature keyId=\"13dfjfhaofjoifjasdlan34663c067\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date\",signature=\"wvmiGG5TZW7NtSjycL2eetbn/jG5FO9+BknJNnnumZQ=\"",

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.

could you please clarify what you mean by WC1 API please?

@Max Daneshvar ,

Here, WC1 API stands for the system which checks the authorization headers and the date headers being sent to it as an API request by the client.

Upvotes
1 1 1 2

I have noticed that postman collection has stopped working since past few hours with the test error of "Status code is 200 | AssertionError: expected false to be truthy" even after completely re-importing and re-adding the key and secret.

Aside from that, another thing that I have noticed is in my code here:

base64_encode(hash_hmac('sha256', $dataToSign, $secret, true))

(added true at the end after I noticed my code is generating a much longer string than it should and the "true" now makes it return the right length) isn't returning the same value from postman!

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.

@Max Daneshvar ,

I just tested your API pilot account with the help of Postman and I was unable to reproduce the error. I called the API endpoint groups and got a 200 ok response code with all the groups available in your account as the response body.

Please send me the screenshot of the Postman so that I can look into it. Please include the Postman Console logs.

Apparently there are some issues with postman itself where the test fails. I have faced it twice today, but the issue goes away after I reboot so this isn't really related to the APIs and rather postman itself.

@Max Daneshvar ,

Yes, you are expected to set the "raw_output" parameter as TRUE, in order to get the correct HMAC.

Check this out.

https://stackoverflow.com/questions/11002603/base64-encode-different-between-java-and-php

Upvotes
1 1 1 2

What I am noticing is, whatever I am doing here, I am unable to generate the same signature code.

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.2k 8 5 6

Hello @Max Daneshvar ,

I am not well versed with PHP curl so I will not be able to help you with the code but your function should generate the same HMAC signature as being produced in Postman for this to work.

In order to make sure that HMAC signature is correct, the value being returned by the dataTosign should be accurate.

You can have a look at our sample code (in JS, JAVA, C#) in the download section of our developer community to understand this.

Please go through the document "security.html" available in the API documentation which explains how to write API requests and what the format of dataTosign value should be.

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 2 2 2

I would be grateful if you could help me, I am using the same code of the question, with the corrections that you indicated, but I cannot make it work, in Postman I do not have problem, it was solved, but the code generated by POSTMAN or the code of the friend return me the same thing.

<body>
\t\t<div>
\t\t\t<p>
\t\t\t<img src="http://statcont.westlaw.com/images/tr_logo_40.gif" width="228" height="48" alt="Thomson Reuters" border="0">
\t\t\t<h1>We&rsquo;re sorry...</h1>
\t\t\t<h2>The page you are trying to display is not available.</h2>
\t\t\t
\t\t</div>
</body>


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.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

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