0

I have tried creating a RESTful API service. I have generated a token by hashing a string (using a randomly generated secret key that is stored in the database) that is returned by the login script on successful login, to the client end as a part of a JSON object. The client passes the token (along with some other fields as a JSON object) as a GET/POST parameter to get access to the other API services. However, it seems that when the token string is passed around as a JSON object, the string gets altered somewhere in the middle, and dehashing it with the secret key at the verification endpoint does not yield the same string as the string that was hashed. Result is an unsuccessful attempt at getting the data secured by the token.

I am adding parts of the code that are relevant:

Login Script

$secret = newsecret($rand);
$token = newtoken($secret, $str);

$qry1 = "UPDATE user_master set user_secret='".$secret."' where user_code='".$uid."'";
$res1 = mysqli_query($conn, $qry1);

$outdata = array("status" => "success", "username" => $un, "uid" => $uid, "token" => $token);
header('Content-type: application/json');
echo json_encode($outdata);

Client JS

$.post("http://www.ckoysolutions.com/apis/login.php", inputs).done(function(data){
    if(data.status=="success") {
        var inputs = '{ '
            +'"uid" : "'+data.uid+'" , '
            +'"token" : "'+data.token+'"'
        +' }';

        window.location='http://hasconpanel.ckoysolutions.com/hasconpanel.php?inputs='+inputs;
    }
    else {
        alert(data.message);
    }
});

Redirected page (http://hasconpanel.ckoysolutions.com/hasconpanel.php) sending token as json as a curl postfield for verification

if(isset($inputs->uid) && isset($inputs->token)) {
    $token = $inputs->token;
    $uid = $inputs->uid;

    $auth_data = array("uid" => $uid, "token" => $token);
    $auth_json = json_encode($auth_data);
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => $auth_json,
        CURLOPT_URL => "http://www.ckoysolutions.com/apis/authuser.php",
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json'
        ]
    ]);
    $result = curl_exec($curl);
    curl_close($curl);

    echo $result;
}

Function used in http://www.ckoysolutions.com/apis/authuser.php to authenticate

$row = mysqli_fetch_array($res);
$secret = $row['user_secret'];
$token = $token;

$un = $row['user_name'];
$words = explode(" ",$un);
$fn = $words[0];
$udetails = $row['user_log'];
$udetails = json_decode($udetails);
$uip = $udetails->ip;
$date_time = $udetails->time;

$str = $date_time.$fn.$uip;
$chkstr = decrypt($secret, $token);

if($str == $chkstr) {
    $outdata = array("status" => "success");
    mysqli_close($conn);
}
else {
    $outdata = array("status" => "failure");
    mysqli_close($conn);
}
header('Content-type: application/json');
echo json_encode($outdata);

Please do suggest what might be going wrong here.

Debopam Parua
  • 460
  • 1
  • 4
  • 24
  • 1
    What you're doing is the same concept as JWT (JSON Web Token). There are many librairies for this https://github.com/firebase/php-jwt maybe you should look at them – Treast May 28 '17 at 05:38
  • @Treast.. Actually I got the idea from JWT, and decided to do something similar. It seemed really secure. And thank you, I will look at this.. :D – Debopam Parua May 28 '17 at 06:04

1 Answers1

1

I had a similar issue to this and found that if the token is passed as a query string parameter and contains the + character it will get removed. I discovered the issue because the call wasn't always breaking. The easiest solution for me was to replace "+" with "P". AJAX POST and Plus Sign ( + ) — How to Encode?

  • Actually I used encodeURI() and decodeURI() for the js part and encodeurl() and decodeurl() for the php part, and I am getting a successful login now, though I am not sure if it will break if the '+' appears again. Thank you by the way. :) – Debopam Parua May 28 '17 at 06:07
  • I ran into the issue with .Net, not php. I was still having the issue despite encoding and decoding, but if it's working for you, that's certainly the cleaner approach. – Greg Hardin May 30 '17 at 19:28
  • I have made it work, though it is a bit messy, apparently, I m having to add urlencode() everytime i pass the token from jquery regardless of whether the token is already encoded or not. – Debopam Parua May 31 '17 at 05:41