/** * Parses a signed_request and validates the signature. * * @param string $signedRequest A signed token * @param string $appSecret * * @return array The payload inside it or null if the sig is wrong */ public static function decode($signedRequest, $appSecret) { if (!$signedRequest || strpos($signedRequest, '.') === false) { Debugger::log('Signed request is invalid! ' . json_encode($signedRequest), 'facebook'); return NULL; } list($encoded_sig, $payload) = explode('.', $signedRequest, 2); // decode the data $sig = Helpers::base64UrlDecode($encoded_sig); $data = Json::decode(Helpers::base64UrlDecode($payload), Json::FORCE_ARRAY); if (!isset($data['algorithm']) || strtoupper($data['algorithm']) !== Configuration::SIGNED_REQUEST_ALGORITHM) { Debugger::log("Unknown algorithm '{$data['algorithm']}', expected " . Configuration::SIGNED_REQUEST_ALGORITHM, 'facebook'); return NULL; } // check sig $expected_sig = hash_hmac('sha256', $payload, $appSecret, $raw = TRUE); if (strlen($expected_sig) !== strlen($sig)) { Debugger::log('Bad Signed JSON signature! Expected ' . Dumper::toText($expected_sig) . ', but given ' . Dumper::toText($sig), 'facebook'); return NULL; } $result = 0; for ($i = 0; $i < strlen($expected_sig); $i++) { $result |= ord($expected_sig[$i]) ^ ord($sig[$i]); } if ($result !== 0) { Debugger::log('Bad Signed JSON signature! Expected ' . Dumper::toText($expected_sig) . ', but given ' . Dumper::toText($sig), 'facebook'); return NULL; } return $data; }