I was having a problem with continuous redirect for my application that is basically requesting basic user info such as name, gender and location.
I went through too much headache until I decided to open up base_facebook.php and trace the flow. I ended up with commenting out the if block that checks whether $sig matches $expected_sig inside the parseSignedRequest function. The application worked fine and displayed the basic information about me. However I wonder if it is safe to do so?!!! and why $expected_sig does not match $sig any help would be appreciated thanks indeed
protected function parseSignedRequest($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = self::base64UrlDecode($encoded_sig);
$data = json_decode(self::base64UrlDecode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
self::errorLog('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload,
$this->getAppSecret(), $raw = true);
var_dump($expected_sig);
echo '<br/><br/><br/>';
var_dump($sig);
// if ($sig !== $expected_sig) {
// self::errorLog('Bad Signed JSON signature!');
// return null;
// }
return $data;
}
I experience similar issue and just found that this is my mistake in supplying the correct configuration parameter when calling
$facebook = new Facebook($config);
This is essential for security reasons. It verifies that the request is coming from facebook because only fb and you know the app secret.
Realistically the only variables that are going to screw this up is the facebook app secret or some sort of modification to the signed_request. I had this same issue when I was testing because I copied the signed request coming in wrong. Make sure to double check everything.
Related
I have seen a few similar questions but I think this is new...
I am trying to add a popover on a blog that will contain a Facebook like button for a Facebook page and wil only show if the user does not already like the Facebook page.
Reading through the documentation this should be achievable with the Graph API pages.isFan method but does this require the user to give permissions? If so would it be possible to not have the app request permissions but rather fail gracefully?
Any help much appreciated.
You can tell if a user likes a page from the signed_request which is sent in the request from facebook. You don't have to query the graph api.
We use c# and get it like so:
protected void Page_Load(object sender, EventArgs e)
{
Result = DecodePayload(Request["signed_request"]);
}
public JObject DecodePayload(string payload)
{
var encoding = new UTF8Encoding();
var decodedJson = payload.Split('.')[1].Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
Json = encoding.GetString(base64JsonArray);
var result = JObject.Parse(Json);
return result;
}
Then in the page
<% if (Result["page"] == null || Result["page"]["liked"] == null || !(bool) Result["page"]["liked"])
{%>
Content if liked
<%}%>
One more important thing as of the 30th March the page layout is changing to timeline and you should be aware of a bug currently that does not refresh the page upon liking it see this:
Does anyone know a fix for the lack of page refresh on facebook timeline pages when liking?
UPDATE
The php for decoding the signed request is:
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, '-_', '+/'));
}
How could i get the userid and name of a user who's visiting my facebook page or atleast after like my page? I've created a fan-gate i.e. one page for not fans and another page for those who liked my page. I wanted to display Thank you Mr. ABC
for fan gate mechanism I have used signed request.
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$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;
}
$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, '-_', '+/'));
}
$liked=0;
if ($_REQUEST) {
$response = parse_signed_request($_REQUEST['signed_request'], FACEBOOK_SECRET);
$liked=$response[page][liked];
}
I can understand that Facebook disallows to access user information from page itself. But as I believe javascript and jquery are client side scripts and using this i could be able to fullfill my requirements. Eventhough I had no luck being success, the idea behind my concept is to access certain tag/selector and retrieve the content inside of parent window of facebook page frame container. i.e.
creating a jquery script to access parent window
Facebook's top menu contains small image thumbnail and Full Name of logged in user
using jquery's tag selector to retrieve the content of that html tag
This is not possible. You would have to create an application and prompt the user for permissions to access their account. Liking a page alone is not sufficient to figure out who the user is.
Finally I found an answer to my question and shared here. Make it useful for you also.
I'm using Facebook connect. Over 50% of registrations are getting a "Bad Signed JSON signature." error. What causes this problem and how is it fixed?
Here is the code:
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');
header('location: /volunteerregistration?error=Facebook has failed to connect. Unknown algorithm. Expected HMAC-SHA256 Please register with Omprakash below. ');
exit;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
header('location: /volunteerregistration?error=Facebook has failed to connect. Bad Signed JSON signature. Please register with Omprakash below.');
exit;
}
return $data;
}
Thank you!
had same problem solved by checking given app_secret to api. I copied an invisible sign/character
50% of registrations that you're doing with known good accounts....or 50% of registration on web site in the wild? If it's in the wild, I would assume it's failed hacking attempts...trying to find sites that don't have the extra $sig !== $expected_sig check as your secure site does. :)
I think this is could happened because your apache server doesn't support for CURL library.
Open your php.ini, find ";extension=php_curl.dll" and then remove ";" it means that your php CURL uncommented.
I have created a application and connected it to a fan page so that application content is loaded in that page.
To access user_id and name of user can only be accessed if user have authorized the application.
How application can be authorized at the same time as user have liked the page?
I mean that when user clicks on like page button application authorization dialog box should also appear. Or if i am wrong please suggest the right way.
--- EDIT ----
I am using php-sdk v3.1.1.
This isn't possible, the page like button is not connected in any way to your application.
What you can do is parse the signed_request parameter which is passed to your application to check if the user has liked the page, if he did you can then check if you can get the user object and redirect him to authorization if needed.
If you don't need the user id or any other extended features (such as posting to the wall) and just want to check if a user has liked the page you can just use the signed request and forget about the rest of the authorization.
You can decode the signed_request using your application secret key and the following function:
function parse_signed_request_outside($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = base64_url_decode_outside($encoded_sig);
$data = json_decode(base64_url_decode_outside($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_outside($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
In order to determine the like you need to do the following:
$secret = "SECRET KEY";
$decodedSignedRequest = parse_signed_request_outside($_REQUEST['signed_request'], $secret);
if ($decodedSignedRequest['page']['liked'] == 1){
{
// load content
}
I was wondering how to access the custom fields people filled in after registering on your site with Facebook registration form.
I understand the usage of the PHP SDK environment a bit, and can access gender, name, etc. easily, but I have no idea how to do this with custom fields you yourself created.
I would prefer to receive an answer related to PHP SDK, but any is good.
thanks in advance!
Once the registration form is submitted, a signed_request holding ALL the data you need will be send back to your server on the URL you specify redirect_uri, how to "extract" these data is explained in the documentation (PHP Example reading signed_request section):
<?php
define('FACEBOOK_APP_ID', 'your_app_id');
define('FACEBOOK_SECRET', 'your_app_secret');
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';
}
?>