Php – How to Read/ Parse Data of Signed_Request from Registration Script in Php 5.1.6

facebookfacebook-php-sdkPHPregistration

I'm trying to implement the Facebook registration script.

The form is getting submitted fine and the server is receiving the signed request. However, it is not able to read/parse the signed request.

I used the script recommended on the registration page https://developers.facebook.com/docs/plugins/registration/ (code below) and all I see for output is:

signed_request contents:

I have verified that the signed_Request is being received. If I pass it to: http://developers.facebook.com/tools/echo?signed_request= I see data.

However on my server with the script below nothing.

The server is http NOT https and using php 5.1.6 (which doesn't have some of the JSON support) Do I need PHP SDK installed? Or the jsonwrapper? I've tried the jsonwrapper but not PHP SDK.

Any help on why the signed_request can not be read would be appreciated.

Code below from facebook

    <?php
    include ('jsonwrapper/jsonwrapper.php');


    define('FACEBOOK_APP_ID', 'XXX');
    define('FACEBOOK_SECRET', 'XXX');

    function parse_signed_request($signed_request, $secret) {
    list($encoded_sig, $payload) = explode('.', $signed_request, 2); 

  // decode the data
  $sig = base64_url_decode($encoded_sig);
  $data = json_decode(base64_url_decode($payload), true);

  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    error_log('Unknown algorithm. Expected HMAC-SHA256');
    return null;
  }

  // check sig
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
  }

  return $data;
}

function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_', '+/'));
}

if ($_REQUEST) {
  echo '<p>signed_request contents:</p>';

  $response = parse_signed_request($_REQUEST['signed_request'], 
                                   FACEBOOK_SECRET);
  echo '<pre>';
  print_r($response);
  echo '</pre>';

} else {
  echo '$_REQUEST is empty';
}
?> 

output is

"signed_request contents:"

If I add:
print_r($_REQUEST); to the script I do see the request but can't parse it

Best Answer

You don't need the PHP SDK for this. It may make it easier to do this and various other things, but it is not necessary if you want to do the decode yourself.

Are you sure you actually have a json_decode function? I don't think it's usually part of jsonwrapper.php, so I suspect your script is crashing on that function call. You can use the following function as a substitute, just change the call to usr_json_decode and include the following at the bottom of your script:

function usr_json_decode($json, $assoc=FALSE, $limit=512, $n=0, $state=0, $waitfor=0)
{
  $val=NULL;
  static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
  static $str_eq = array("n"=>"\012", "r"=>"\015", "\\"=>"\\", '"'=>'"', "f"=>"\f", "b"=>"\b", "t"=>"\t", "/"=>"/");
  for (; $n<strlen($json); /*n*/)
    {
    $c=$json[$n];
    if ($state==='"')
      {
      if ($c=='\\')
        {
        $c=$json[++$n];
        if (isset($str_eq[$c]))
          $val.=$str_eq[$c];
        else if ($c=='u')
          {
          $hex=hexdec(substr($json, $n+1, 4));
          $n+=4;
          if ($hex<0x80) $val .= chr($hex);
          else if ($hex<0x800) $val.=chr(0xC0+$hex>>6).chr(0x80+$hex&63);
          else if ($hex<=0xFFFF) $val.=chr(0xE0+$hex>>12).chr(0x80+($hex>>6)&63).chr(0x80+$hex&63);
          }
        else
          $val.="\\".$c;
        }
      else if ($c=='"') $state=0;
      else $val.=$c;
      }
    else if ($waitfor && (strpos($waitfor, $c)!==false))
      return array($val, $n);
    else if ($state===']')
      {
      list($v, $n)=usr_json_decode($json, $assoc, $limit, $n, 0, ",]");
      $val[]=$v;
      if ($json[$n]=="]") return array($val, $n);
      }
    else
      {
      if (preg_match("/\s/", $c)) { }
      else if ($c=='"') $state='"';
      else if ($c=="{")
        {
        list($val, $n)=usr_json_decode($json, $assoc, $limit-1, $n+1, '}', "}");
        if ($val && $n) $val=$assoc?(array)$val:(object)$val;
        }
      else if ($c=="[")
        list($val, $n)=usr_json_decode($json, $assoc, $limit-1, $n+1, ']', "]");
      elseif (($c=="/") && ($json[$n+1]=="*"))
        ($n=strpos($json, "*/", $n+1)) or ($n=strlen($json));
      elseif (preg_match("#^(-?\d+(?:\.\d+)?)(?:[eE]([-+]?\d+))?#", substr($json, $n), $uu))
        {
        $val = $uu[1];
        $n+=strlen($uu[0])-1;
        if (strpos($val, ".")) $val=(float)$val;
        else if ($val[0]=="0") $val=octdec($val);
        else $val=(int)$val;
        if (isset($uu[2])) $val*=pow(10, (int)$uu[2]);
        }
      else if (preg_match("#^(true|false|null)\b#", substr($json, $n), $uu))
        {
        $val=$lang_eq[$uu[1]];
        $n+=strlen($uu[1])-1;
        }
      else
        {
        return $waitfor ? array(NULL, 1<<30) : NULL;
        }
      }
    if ($n===NULL) return NULL;
    $n++;
    }
  return ($val);
}

BTW though, this should be very easy to track down using your error log, turning on extra debugging and adding some echo or var_dump statements as necessary.

Related Topic