-2

I'm generating a public key on the server side to pass on the client side to render an iframe (hosted by a third party).

I'm getting a whole chunk of data from the JWK response, but I only need the keyID value.

{ "data": "{\"keyId\":\"eyJraWQiOiIzZyIsImFsZyI6IlJTMjU2In0.eyJmbHgiOnsicGF0aCI6Ii9mbGV4L3YxL3Rva2Vucz9mb3JtYXRcdTAwM2RKV0UiLCJkYXRhIjoiOFZ6WnhyUHd2b1dRb1I0QTVTRWNteEFBRUliNlJsT1YzdGU4UUxGdmEwb08wTEliWkhtWmE4Z2ZqT0lSWklmS1FaUElRYmhaZHVlRFNwQzZZZllUanF0cU94d2xtUVlQa1FzZUcrL05WUGlBbUZUdGtUNjlUbXAyb3pEOWJqT0NyVFlQIiwib3JpZ2luIjoiaHR0cHM6Ly90ZXN0ZmxleC5jeWJlcnNvdXJjZS5jb20iLCJqd2siOnsia3R5IjoiUlNBIiwiZSI6IkFRQUIiLCJ1c2UiOiJlbmMiLCJuIjoiaGNLRlU5UllCR0VwY1JyR3FQQ2J1U3BlOFdyeTRRUUNvMUdiRml4ZHdWMUtuN09BMHQtRDdXM2tvUjN6MDc3UndnYnBldTdvbV8xd0ZrRjVRLTBNeVNfdzk3TklmaVk1OVNLb3JqdWhfQmt2NHdJVGVUbm9LN2ZROHJyOTJSOUNKTFp6UFdlUVJPMDVxeWxiLVdVWUJvOU5sa2QwZHl6b2RlbEoxWVRzQ1JzYlRVc0ZRMUxKZHVIWWw0X3kzTF9FbnkwaG1mSFg5cll4U2ozamhmZVpZYVhYa0wtdERCa2k5VF9zXzhzb19RQjNLN29oR2tqSDU1TUQwRkdDNzVpRS1UcmtqNFd0cWNyYjI3S3BNSzdXWm1qSnJUMFE0bzlMMTBURXJvZE1HeEpfTm5IMGdSYmUwTFVSOWhaVnUzMG9tWkdrQVhfQXhUa1VJWktXQzZENkJ3Iiwia2lkIjoiMDd1SlMwT0dpR2pObzF6ejRTbGFpZUIzQkprSWc1bVAifX0sImN0eCI6W3siZGF0YSI6eyJ0YXJnZXRPcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MiJdLCJtZk9yaWdpbiI6Imh0dHBzOi8vdGVzdGZsZXguY3liZXJzb3VyY2UuY29tIn0sInR5cGUiOiJtZi0wLjExLjAifV0sImlzcyI6IkZsZXggQVBJIiwiZXhwIjoxNTgwMTg5NDA2LCJpYXQiOjE1ODAxODg1MDYsImp0aSI6InNYYWNWSm43bkI1a1ZvSnIifQ.Hr-DwfFv-90bBtUWhACXwkhVFefh7fNOV9FS5Epu5fcL7Ji_pE9GHQIhaX5F31VM-EAOz55gG0eYnEu7ZAptR1mq3WgxNx3Af9ngKpbl4ZTb9cUxjGf3DdGJ1-J26aziJx3GcaZREfFyabDWbThyKlGTxSbnGHb7-UcQ_MPmh-znt_691y_gX9Qo8fe6XeJw8-Ir4XwwznjNLa31-EctYfnYUbfOnjR_8rfuFNnulvQecHs1e4zFVVAqm8mqex-umdlPbPUGT8xzYN-G0oLMdj3uMAAeSuyrdAifVXWSXyyyBHU5rIp-8anGWj_9RQrwvOH7MOIerV3Lej1-lEOxTw\",\"der\":null,\"jwk\":null}" }

I need the keyID value and pass it in the client side on a variable called "captureContext".

This is my client side code but it's returning me all the data above:

var captureContext = <?php echo json_encode($body)?>;
console.log(captureContext);

This is how I'm generating the public key in the server side:

<?php

define ('HMAC_SHA256', 'HmacSHA256');

//Step 0.  Set Secret Key a
define ('SHARED_SECRET_KEY', '--insert shared secret--');
define ('KEY_ID','--insert key ID--');
define ('MERCHANT_ID','--insert merchant ID--');

define('TARGET_ORIGIN',"http://localhost:8082");
define ('SECURE_HTTPS','https://');
define('HOST','apitest.cybersource.com');
define('DESTINATION_RESOURCE','flex/v1/keys?format=JWT'); 

define('SHA256','sha256');
define('ENCRYPTION_TYPE','RsaOaep256');


function loggingHelper( $response, $curl, $testInfo, $requestBody ) {
        printf("%s\n",$testInfo);
        if(!$response) {
            printf ('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
        } else {
            if (empty($requestBody) == false && $requestBody != '') {
                $json = json_decode($requestBody);
                $json = json_encode($json, JSON_PRETTY_PRINT);
                printf("Request Body : %s\n", $json);
            }
            $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
            $header = substr($response, 0, $header_size);
            $body = substr($response, $header_size);
            printf ("Response Status: %s\n",curl_getinfo($curl, CURLINFO_HTTP_CODE));
            printf($header);
            if (empty($body) == false && $body != '') {
                $json = json_decode($body);
                $json = json_encode($json, JSON_PRETTY_PRINT);
                printf("Response Body : %s\n", $json);
            }

        }
    }

function getSignature($params){
       return signData(buildDataStringToSign($params), SHARED_SECRET_KEY); 

}

function getHeadersString($params) {


   $headerStringArray = array();
   foreach($params as $field => $value){
        $headerStringArray[] = $field;
    } 
    return implode(" ",$headerStringArray);
}

function buildDataStringToSign($params) {
        $dataStringArray = array();

        foreach ($params as $field => $value) {
           $dataStringArray[] = $field . ": " . $value;
        }
        return implode("\n",$dataStringArray);
}

function jdebug($variable,$text){

    echo "<br>=====".$text."=====<br>";


    var_dump($variable);

    echo "<br>=====".$text."=====<br>";


}


function signData($data, $secretKey) {
    //Remember, the key is provided in a base64 format, so it must be decoded before using in the hmac

    return base64_encode(hash_hmac(SHA256, $data, base64_decode($secretKey),true));

}


function commaSeparate ($dataToSign) {
    return implode(",",$dataToSign);
}

function getServerTime() {

     return gmdate("D, d M Y H:i:s \G\M\T");
 }

function getDigestHeader($params) {

    return "SHA-256=".base64_encode(hash(SHA256,$params,true));

}

function getDigestBody() {

      $digestBody = Array("encryptionType" => ENCRYPTION_TYPE,
                          "targetOrigin" => TARGET_ORIGIN );

    //return  "{\n  \"encryptionType\": \"".ENCRYPTION_TYPE."\",\n  \"targetOrigin\": \"".TARGET_ORIGIN."\"\n}";
    return  json_encode($digestBody);

}

    $digestBody = getDigestBody();

    $digestHash = getDigestHeader($digestBody);

    $serverTime = getServerTime();


    $signedHeaders['host'] = HOST;
    $signedHeaders['date'] = $serverTime;

    $signedHeaders['(request-target)'] = 'post /'.DESTINATION_RESOURCE;
    $signedHeaders['digest'] = $digestHash;


    $signedHeaders['v-c-merchant-id'] = MERCHANT_ID;


    $signature = getSignature($signedHeaders);


   $signatureHeader = "";

   $signatureHeader.="keyid=\"".KEY_ID."\"".", ";
   $signatureHeader.="algorithm=\"".HMAC_SHA256."\"".", ";
   $signatureHeader.="headers=\"".getHeadersString($signedHeaders)."\"".", ";
   $signatureHeader.="signature=\"".$signature."\"";

        $curl = curl_init ();

        $headers = array("host: ".$signedHeaders['host'],
                          "date: ".$signedHeaders['date'],
                          "digest: ".$signedHeaders['digest'],
                          "signature: ".$signatureHeader,
                          "Content-Type: application/json; charset=utf-8",
                          "v-c-merchant-id: ".$signedHeaders['v-c-merchant-id']);

        $absUrl = SECURE_HTTPS.HOST."/".DESTINATION_RESOURCE;


        $opts = array ();

        $opts [CURLOPT_POST] = 1;
        $opts [CURLOPT_POSTFIELDS] = $digestBody;
        $opts [CURLOPT_PROTOCOLS] = CURLPROTO_HTTPS;
        $opts [CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_2;
        $opts [CURLOPT_URL] = $absUrl;
        $opts [CURLOPT_RETURNTRANSFER] = true;
        $opts [CURLOPT_CONNECTTIMEOUT] = 50;
        $opts [CURLOPT_TIMEOUT] = 100;
        $opts [CURLOPT_HTTPHEADER] = $headers;
        $opts [CURLOPT_HEADER] = 1;


        curl_setopt_array ( $curl, $opts );

        $response = curl_exec ( $curl );


        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);


        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);
        $body = substr($response, $header_size);


        $response = json_decode($body);
        $jwk = $response->jwk;


        curl_close ( $curl );

?>

Hope you can help me out! Thank you in advance!

yukimiya
  • 13
  • 5
  • https://www.w3schools.com/js/js_json_objects.asp -> Accessing Object Values – jasie Jan 28 '20 at 07:33
  • 1
    OMG I dropped this last year but had to do it again and I didn't saw your answer, but this is the answer I'm looking for~~ Thank you so much, sorry it's late! :D @jasie – yukimiya Apr 09 '21 at 18:33

2 Answers2

0

I have tried my best to understand the code you pasted, but it is hard to say how did the response is being generated/responsed from server, because from my scanning of the code, there was no indication if first part code and the second are both on the server side, or first part is a test code on the client side (that first part is clearly a code mixture with php, such as js+php).

So there are two possibilities:

  1. both code are on server side
  2. only second code is on server side

1: if the first part of the code is on the server side and is being requested from client side, and you want to split is result and send only the key back, all you need to do is:

// if $body is an array in php
var captureContext = <?php echo $body['data']['keyId'] ?>;

// if $body is an object in php
var captureContext = <?php echo $body->data->keyId ?>;

2: if the first part should be client side, which mean the somewhere in the second part responsed the data back to the client request (normally with an echo), then you need to find the response data carrier (e.g. $response in the second part) and do:

# if $response is the final response data carrier/variable
echo $response->data->keyId;

if the first part of the code is what the client side should be getting and your asking how to split the key from the whole response data:

var captureContext = <?php echo json_encode($body)?>;
var resp = JSON.parse(captureContext);
var keyID = resp.data.keyId;
console.log(keyID);

if this still gives you an error of undefined to keyId, try:

var captureContext = <?php echo json_encode($body)?>;
var resp = JSON.parse(captureContext);
var respData = JSON.parse(resp.data);
var keyID = respData.keyId;
console.log(keyID);

the reason of such error is because I noticed that your post of JWK from console.log() shows a data and keyId in defferent symbols, " and \", and the whole data value is under a String format, so you might need to translate twice for another inner JSON structure.

From my guess the first code and the second are sharing variable names, and if $body are the same variable, then split keyId from a JSON format is a very easy process.

  • Sorry I'm not clear enough. But you're right, the first code is from the client side and the 2nd code is for the server side. And yes they're sharing the variable name $body which contains the JWK Response above. I tried this code but I didn't see they keyID value in console log and I can't still render the iframe. ``` var captureContext = ; var resp = JSON.parse(captureContext); var keyID = resp.keyId; console.log(keyID); ``` Thank you for your response! – yukimiya Jan 28 '20 at 08:14
  • sorry, it was my mistake in the last part of the code `keyID`, this is because you have it under property `data`. check it again, I have edited and fixed it. But still, if the response to the client side should only contain the keyID instead of full JWK data, for security reason, the best way is still splitting this ID from the whole JWK on server side. However, I guess that JWK is the correct API your trying to send back to the client. – DeadlYBlinder Jan 28 '20 at 08:36
  • by the way, there is another unclear part that may cause an error, the data you paste for JWK is started with { "data": ... } and the value that follows is { "\keyId"\: "\..."\ }. Note that a console.log() may output an object like the JWK you posted. – DeadlYBlinder Jan 28 '20 at 09:03
  • Hmm I tried both codes above but there's no keyID value returning in console log and iframe can't still be rendered. How to split the keyID from the whole JWK on server side? I tried below but I'm having Undefined index: data and I received a null JWK response. $body = json_decode($body, true); $body = json_decode($body['data']['keyId'], true); $keyId = $body['keyId']; Also if this is the code on server side,how should I specify it in client side? Thank you! – yukimiya Jan 28 '20 at 09:56
  • can you try the following steps and give me the output, so that I could tell you where the key is: a) `console.log(captureContext);` b) `console.log(JSON.parse(captureContext));` c) `console.log(JSON.parse(captureContext).data);` d) `console.log(JSON.parse(JSON.parse(captureContext).data));` e) `console.log(JSON.parse(JSON.parse(captureContext).data).keyId);` – DeadlYBlinder Jan 28 '20 at 12:06
  • no luck.T.T all doesn't return anything in console log. I'm thinking to just parse the JWK response and extract the keyId value in the server side then pass the keyId value itself on the client side but I couldn't find a way to do it. T.T – yukimiya Jan 29 '20 at 09:06
  • the a) `console.log(captureContext);` script is exactly same one as you post in your quiz, and I assume that gives the result you output into the console log, and if a) did not output what you used to get, then I guess there was some thing changed against your original code. Try to roll-back, and retry these logs, specially a) should at least result what you posted at the beginning. – DeadlYBlinder Jan 30 '20 at 12:30
0

I tried something and i think i got it:

$body = '{ "data": "{\"keyId\":\"eyJraWQiOiIzZyIsImFsZyI6IlJTMjU2In0.eyJmbHgiOnsicGF0aCI6Ii9mbGV4L3YxL3Rva2Vucz9mb3JtYXRcdTAwM2RKV0UiLCJkYXRhIjoiOFZ6WnhyUHd2b1dRb1I0QTVTRWNteEFBRUliNlJsT1YzdGU4UUxGdmEwb08wTEliWkhtWmE4Z2ZqT0lSWklmS1FaUElRYmhaZHVlRFNwQzZZZllUanF0cU94d2xtUVlQa1FzZUcrL05WUGlBbUZUdGtUNjlUbXAyb3pEOWJqT0NyVFlQIiwib3JpZ2luIjoiaHR0cHM6Ly90ZXN0ZmxleC5jeWJlcnNvdXJjZS5jb20iLCJqd2siOnsia3R5IjoiUlNBIiwiZSI6IkFRQUIiLCJ1c2UiOiJlbmMiLCJuIjoiaGNLRlU5UllCR0VwY1JyR3FQQ2J1U3BlOFdyeTRRUUNvMUdiRml4ZHdWMUtuN09BMHQtRDdXM2tvUjN6MDc3UndnYnBldTdvbV8xd0ZrRjVRLTBNeVNfdzk3TklmaVk1OVNLb3JqdWhfQmt2NHdJVGVUbm9LN2ZROHJyOTJSOUNKTFp6UFdlUVJPMDVxeWxiLVdVWUJvOU5sa2QwZHl6b2RlbEoxWVRzQ1JzYlRVc0ZRMUxKZHVIWWw0X3kzTF9FbnkwaG1mSFg5cll4U2ozamhmZVpZYVhYa0wtdERCa2k5VF9zXzhzb19RQjNLN29oR2tqSDU1TUQwRkdDNzVpRS1UcmtqNFd0cWNyYjI3S3BNSzdXWm1qSnJUMFE0bzlMMTBURXJvZE1HeEpfTm5IMGdSYmUwTFVSOWhaVnUzMG9tWkdrQVhfQXhUa1VJWktXQzZENkJ3Iiwia2lkIjoiMDd1SlMwT0dpR2pObzF6ejRTbGFpZUIzQkprSWc1bVAifX0sImN0eCI6W3siZGF0YSI6eyJ0YXJnZXRPcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MiJdLCJtZk9yaWdpbiI6Imh0dHBzOi8vdGVzdGZsZXguY3liZXJzb3VyY2UuY29tIn0sInR5cGUiOiJtZi0wLjExLjAifV0sImlzcyI6IkZsZXggQVBJIiwiZXhwIjoxNTgwMTg5NDA2LCJpYXQiOjE1ODAxODg1MDYsImp0aSI6InNYYWNWSm43bkI1a1ZvSnIifQ.Hr-DwfFv-90bBtUWhACXwkhVFefh7fNOV9FS5Epu5fcL7Ji_pE9GHQIhaX5F31VM-EAOz55gG0eYnEu7ZAptR1mq3WgxNx3Af9ngKpbl4ZTb9cUxjGf3DdGJ1-J26aziJx3GcaZREfFyabDWbThyKlGTxSbnGHb7-UcQ_MPmh-znt_691y_gX9Qo8fe6XeJw8-Ir4XwwznjNLa31-EctYfnYUbfOnjR_8rfuFNnulvQecHs1e4zFVVAqm8mqex-umdlPbPUGT8xzYN-G0oLMdj3uMAAeSuyrdAifVXWSXyyyBHU5rIp-8anGWj_9RQrwvOH7MOIerV3Lej1-lEOxTw\",\"der\":null,\"jwk\":null}" }';

$body = json_decode($body, true);
$body = json_decode($body['data'], true);
$keyId = $body['keyId'];

And since you tagged PHP in it this is my server side answer.

EDIT:

You have to make your $body variable a string. Put quotes around it. Tested and confirmed, this works.

Gobbin
  • 530
  • 3
  • 17
  • Hmmm the JWK Response is unique for every transaction so I cannot hardcode the $body like this. I tried this but got an error of Undefined index: data – yukimiya Jan 28 '20 at 08:34