Facebook PHP app on Heroku not receiving signed_request - php

I have added a PHP/JavaScript app as a Facebook page tab, and I'm hosting it on Heroku. However it's not receiving the signed_request. It comes through just fine when I host the tab on my own server, just not on Heroku.
Here is the code:
require_once('sdk/src/facebook.php');
$facebook = new Facebook(array(
'appId' => AppInfo::appID(),
'secret' => AppInfo::appSecret(),
'sharedSession' => true,
'trustForwarded' => true,
'cookie' => true
));
$signed_request = $facebook->getSignedRequest();
$liked = $signed_request['page']['liked'];
if( $liked ) {
echo('fan');
}
else {
echo('not a fan ') ;
}
What could the issue be?

I had the same problem. If you're using heroku's base php template get rid of this code, that enforces the https on production:
// Enforce https on production
if (substr(AppInfo::getUrl(), 0, 8) != 'https://' && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
header('Location: https://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit();
}
When the user doesn't uses the secure connection, this line redirects to another page losing the POST requests.
You can try and send the signed_request with with GET method if you want to keep it. It may look like this:
// Enforce https on production
if (substr(AppInfo::getUrl(), 0, 8) != 'https://' && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
$signed_request = "";
if (isset($_REQUEST['signed_request'])){
$signed_request = "&signed_request=" . $_REQUEST['signed_request'];
}
header('Location: https://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . "?" . $signed_request );
exit();
}
That's my solution.

Related

Facebook API - Subscriptions Timeout in callback

I have a really strange problem in PHP with the Facebook API. All this code is working in my testing server (shared hosting). But when I run it in the production server (Heroku) I get an error.
What I am trying to do is to receive realtime updates from Facebook when my app users likes (or unlikes) a new page.
This is the documentation that Facebook provides: https://developers.facebook.com/docs/graph-api/real-time-updates
My code to subscribe:
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $app_secret,
'cookie' => true
));
$facebook->api(
"/" . $app_id . "/subscriptions", "POST", array(
'object' => 'user',
'callback_url' => 'http://' . $url . '/rtu/callback',
'fields' => 'likes',
'verify_token' => $rtu_verify_token,
'access_token' => $app_id . "|" . $app_secret
)
);
My code in the callback:
if (isset($_GET['hub_verify_token']) && isset($_GET['hub_challenge'])) {
$rtu_verify_token = Config::get('variables.rtu_verify_token');
if (($_GET['hub_verify_token'] == $rtu_verify_token)) {
echo $_GET['hub_challenge'];
die();
}
}
$data = file_get_contents("php://input");
$json = json_decode($data);
The error:
FacebookApiException (#2200) callback verification failed: Operation
timed out after 6001 milliseconds with 0 bytes received
I have already verify the app_id, url and the app_secret variables.
Again, this works in my testing server, but not in Heroku.
I even tried not to use the Facebook API and make a cURL call, but I got the same error.
I'm thinking that maybe has something to do with Heroku, but i couldn't find any evidence.
Thanks
Your server must be reachable from the internet, and be able to process concurrent requests, because facebook sends verification requests simultaneously.

getLoginUrl( ) not working / getUser() return 0

$url = 'http://xxxxxx.com:8052/php/myproject/';
$loginUrl = $facebook->getLoginUrl(array(
'scope' => 'publish_stream,email',
'redirect_uri' => $url,
));
$facebook->getUser() will have 0.
That is because my server is using port 8052 for http(Sharing IP with other server)
It is not working if I use port number at redirect_uri.
I am sure the domain setting is correct at Facebook.com
How to solve this?
This is not programming problem, i am using port forward for the tomcat server. 8052->tomcat
You can't get correct 8052 port if you are using port forward, always get 80 by php code.
In the Facebook SDK, base_facebook.php
public function getLoginUrl($params=array()) {
$this->establishCSRFTokenState();
$currentUrl = $this->getCurrentUrl();
You can see it will get url from function getCurrentUrl, go to edit it
// use port if non default
if(isset($_SESSION['server_port'])){
$port = $_SESSION['server_port'];
}else{
$port =
isset($parts['port']) &&
(($protocol === 'http://' && $parts['port'] !== 80) ||
($protocol === 'https://' && $parts['port'] !== 443))
? ':' . $parts['port'] : '';
}
// rebuild
return $protocol . $parts['host'] .':'. $port . $parts['path'] . $query;
I preset session server_port by using javascript(can get correct port), now use it as the port by the above code, the try the following code can get correct url which can getUser() after login.
$login_url = $facebook->getLoginUrl()
PS: It seems okay if input url by my self
$login_url = $facebook->getLoginUrl(array(
'scope' => 'email,publish_stream',
'redirect_uri' => $url
));

Why is getUser() always returning 0? [duplicate]

This question already exists:
Facebook getUser() always returns 0 [duplicate]
Closed 10 years ago.
This Facebook PHP SDK is driving me CRAZY!
getUser() always return 0
let me explain what I do:
$facebook = new Facebook(array(
'appId' => FACEBOOK_APP_ID,
'secret' => FACEBOOK_SECRET,
));
$user = $facebook->getUser();
if ($user === 0)
{
$loginUrl = $facebook->getLoginUrl(array(
'scope' => 'email, publish_stream',
'redirect_uri' => FB_REDIRECT_URI
));
echo "<script type='text/javascript'>window.location = '$loginUrl';</script>";
exit();
}
simple code, equals to the example. Good...
I have this code in login.php and complete.php
I send the request from login.php and set the redirect_uri to complete.php (the same I wrote in Website with Facebook Login...obviously a complete URL like https://www.example.com/complete.php)
I really do not understand Why I still get 0!
It is not possible, Im logged in Facebook following the LoginURL.
I also passed the "permissions" with the URL.
I already registered at this app, so I really do not understand the reason why this SDK is continuing to return 0.
Could someone help me?
INFO:
I only have selected Website with Facebook Login, nothing else... "App on Facebook" is not selected.
EDIT:
https://www.facebook.com/login.php?api_key=216182291818102&skip_api_login=1&display=page&cancel_url=https%3A%2F%2Fwww.example.com%2Fusers%2Fcomplete%2F%3Ferror_reason%3Duser_denied%26error%3Daccess_denied%26error_description%3DThe%2Buser%2Bdenied%2Byour%2Brequest.%26state%3D720fab495a21639032816d3c688ae87b&fbconnect=1&next=https%3A%2F%2Fwww.facebook.com%2Fdialog%2Fpermissions.request%3F_path%3Dpermissions.request%26app_id%3D216182291818102%26redirect_uri%3Dhttps%253A%252F%252Fwww.example.com%252Fusers%252Fcomplete%252F%26display%3Dpage%26response_type%3Dcode%26state%3D720fab495a21639032816d3c688ae87b%26perms%3Duser_birthday%252Cemail%26fbconnect%3D1%26from_login%3D1%26client_id%3D216182291818102&rcount=1
i am used same example and it's work for me.
my connection is like this,try to add cookie = true and check, hope will work for you
$facebook = new Facebook(array(
'appId' => FACEBOOK_APP_ID,
'secret' => FACEBOOK_SECRET,
'cookie' => true,
));
Where did you get the example from? This is from the FB Developer page (https://developers.facebook.com/docs/authentication/server-side/):
<?php
$app_id = "YOUR_APP_ID";
$app_secret = "YOUR_APP_SECRET";
$my_url = "YOUR_URL";
session_start();
$code = $_REQUEST["code"];
if(empty($code)) {
$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
$dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
. $_SESSION['state'];
echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
if($_SESSION['state'] && ($_SESSION['state'] === $_REQUEST['state'])) {
$token_url = "https://graph.facebook.com/oauth/access_token?"
. "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret . "&code=" . $code;
$response = file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$graph_url = "https://graph.facebook.com/me?access_token="
. $params['access_token'];
$user = json_decode(file_get_contents($graph_url));
echo("Hello " . $user->name);
}
else {
echo("The state does not match. You may be a victim of CSRF.");
}
?>
Your code is looking good. You should provide one more parameter to facebook array that is cookie=>true. You should refer the following tutorial which worked for me.
http://www.9lessons.info/2011/02/login-with-facebook-and-twitter.html
Hope it will work for you.
Now I am posting the configuration of APP.
App ID/API Key
xxxxxxxxxxxxxxxxxx // your App ID
App Secret
xxxxxxxxxxxxxxxxxxxxxxx //Your secret key
Site URL
http://localhost/ //your site url
Contact Email
example#example.com //your email id
Support URL
http://localhost //your support url
I only provided this much information and its perfectly working for me.
Try this
$facebook = new Facebook(array(
'appId' => FACEBOOK_APP_ID,
'secret' => FACEBOOK_SECRET,
'cookie' => true,
));
and first you login in facebook account then execute this code.
$user=$facebook->getUser();

facebook iframe app; php sdk getUser() returns valid id on page one but not for any other page

I have a facebook iframe app which correctly logs in and authorizes the app, but getUser() only works on the first page. As soon as a user clicks a link to a new page within the iframe, getUser() returns 0.
What's strange is that this same code works for another app... I do all the clicking I want and getUser() returns a valid ID.
The app that doesn't work: https://apps.facebook.com/celestial_glory/
The one that does (same codebase): https://apps.facebook.com/uprisingstlouis/
Here's the code I am using:
require_once ('fb/facebook.php');
// snip... set $app_id, $secret, and $canvas_page
// first, try normal facebook getUser(). If that works, awesome.
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $secret,
));
$signed_request = $_REQUEST['signed_request'];
// Get User ID
$user = $facebook->getUser();
if ($user != '0') return 'fb=' . $user; // works once
// getUser() didn't work. Try oAuth. Maybe user needs to log in or
// authorize the game?
$auth_url = 'http://www.facebook.com/dialog/oauth?client_id='
. $app_id . '&redirect_uri=' . urlencode($canvas_page);
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
if (empty($data["user_id"])) {
echo '<a target="_top" href="' . $auth_url . '">Login to Facebook</a>';
exit;
// normally we would auto-redirect, but with a uid of 0, this just auto-redirects
// echo("<script> top.location.href='" . $auth_url . "'</script>");
} else {
return 'fb=' . $data['user_id'];
}
any ideas? I have triple-checked app ids and secrets and canvas pages. If those were wrong, I expect no page, not even the first, would work.
Change Facebook PHP-SDK initialization to:
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $secret,
'cookie' => true // this!
));
getUser works on the first page because it can get the user from signed_request (POST'ed by Facebook to your canvas page URL). Thus you need some way to track your user once he starts navigation deeper within your application. You could pass signed_request somehow all by yourself or simply enable built-in PHP-SDK cookie support as suggested above.

Facebook Authorization for an iFrame App in PHP

I need to get the User ID of a user hitting a Facebook iFrame application. While sifting through all of the bogus and outdated information, I think I've come across the correct info.
When the user hits the page, I need to have them authorize the app. In my PHP I do this:
$facebook = new Facebook($appData);
$user = $facebook->getUser();
if(!$user) {
echo '<script>top.location.href="'.$facebook->getLoginUrl().'";</script>';
die();
}
This gives me the authorization request, but then pushes me back to my server, not the iFrame App's URL (http://app.facebook.com/blah). I manually constructed the URL and tried to set the URL to the app.facebook.com URI but then it I get an error saying the URL is not valid for the app.
How do you get it to redirect back to the app after authorization? This app will live inside Facebook, not be generally accessible outside, so I'm not looking for Facebook Connect login.
Edit
This is the exact error I get when I fiddle with the request_uri:
API Error Code: 191
API Error Description: The specified URL is not owned by the application
Error Message: Invalid redirect_uri: Given URL is not allowed by the Application configuration.
Have you tried setting the redirect_uri parameter.
if(!$user) {
$params = array('redirect_uri' => 'http://app.facebook.com/blah/');
die('<script>top.location.href="'.$facebook->getLoginUrl($params).'";</script>');
}
Go to:
http://developers.facebook.com/apps
In the your developer application settings on you need to change the URL settings so that Facebook knows your app is a canvas app. In the settings, be sure to delete all the URLs that are in the Web tab and then make sure that all the URLs are appropriately set in the On Facebook tab.
You can following sample code to authorize facebook application in an iframe app using graph api
<?php
ob_start();
session_start();
/*
* App Config
*/
$config= array(
'appId' => 'APPID',
'secret' => 'APPSECRET',
'canvas'=>"http://apps.facebook.com/sampleapp/");
$GRAPH_URL = "https://graph.facebook.com/";
$scope = "publish_stream,email";
$auth_url = "https://www.facebook.com/dialog/oauth?client_id=".$config['appId']."&redirect_uri=".urlencode($config['canvas']). "&scope=" . $scope;
$signed_request = $_REQUEST["signed_request"];
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
if(is_array($data)){
$authToken = $data['oauth_token'];
$userId = $data['user_id'];
$_SESSION['auth_token'] = $authToken;
//check for permission//
$permissions = json_decode(curl_get_file_contents($GRAPH_URL . "me/permissions?access_token=" . $authToken), TRUE);
if(array_key_exists('publish_stream', $permissions['data'][0]) ) {
$post = array('client_id'=>$config['appId'],'redirect_uri'=>$config['canvas'].'','client_secret'=>$config['secret'],'type'=>'client_cred');
$token_url="https://graph.facebook.com/oauth/access_token";
$response = curlpost($token_url,$post);
$params = explode('&',$response);
if(isset($params[0])){
$token = explode('=',$params[0]);
if($token[0]=='access_token'){
$access_token = $token[1];
$_SESSION['access_token']=$access_token;
$_SESSION['authorized']=1;
echo("<script> top.location.href='" . $config['canvas']."home.php'; </script>");
}
}else{
echo("<script> top.location.href='" . $config['canvas']."error.php'; </script>");
}
}else{
$url='https://graph.facebook.com/oauth/authorize?client_id='.$config['appId'].'&redirect_uri='.urlencode($config['canvas']).'&display=page&scope=publish_stream,email&type=user_agent';
echo("<script> top.location.href='" . $url. "'</script>");
}
}else{
echo("<script> top.location.href='" . $config['canvas']."error.php';</script>");
}
?>
Check this link for details
http://forum.bharathlisting.com/showthread.php?tid=13&pid=20#pid20

Categories