FB App: Pulling user data from app - php

Scenario
Facebook app which resides on User A's profile (in a tab called Welcome). User A can fill out a Welcome message and update the message.
User B comes to User A's profile, clicks on the Welcome tab and views the Welcome message written by User A.
I understand how to complete the majority of my application and imaging that I will produce the response based on a DB lookup of a field associated with User A's Facebook ID.
What I don't understand is how to grab the User ID value of the user who installed that instance of the APP (User A) or how to grab the User ID of the profile that User B is currently on (Which also happens to be User A).
Any ideas on how best to attack this?

Found the answer. When your application is installed as a tab then the profile of the user along with other parameters are passed in an encoded string. Here is an example of how I pulled the profile_id.
function getProfileID($post){
global $FB_secret;
$SR = $post['signed_request'];
$PSR = parse_signed_request($SR,$FB_secret);
return $PSR['profile_id'];
}
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, '-_', '+/'));
}
Add those functions then add the following command somewhere:
$profile_user = getProfileID($_POST);
Please note that the script assumes that you will assign the secret key value to $FB_secret to work properly.

Related

facebook data deletion callback implementation in laravel using socialite

I am implementing facebook data deletion callback but I got really lost and i can't continue on the JSON response that facebook is expecting.
Return a JSON response that contains a URL where the user can check the status of their deletion request and an alphanumeric confirmation code. The JSON response has the following form:
{ url: '<url>', confirmation_code: '<code>' }
that is the part that I got lost and stuck. My question is
what is the URL should do or show.
what is the logic between the confirmation code
so far here is what I did on my controller.
<?php
namespace App\Http\Controllers\User\Auth\Socialite;
use App\Models\User;
use Illuminate\Http\Request;
class FacebookSocialLoginController extends SocialLoginFactory
{
public function provider(): string
{
return 'facebook';
}
public function dataDeletionCallback(Request $request)
{
$signed_request = $request->get('signed_request');
$data = $this->parse_signed_request($signed_request);
$user_id = $data['user_id'];
// here will delete the user base on the user_id from facebook
User::where([
['provider' => 'facebook'],
['provider_id' => $user_id]
])->forceDelete();
// here will check if the user is deleted
$isDeleted = User::withTrashed()->where([
['provider' => 'facebook'],
['provider_id' => $user_id]
])->find();
if ($isDeleted ===null) {
return response()->json([
'url' => '', // <------ i dont know what to put on this or what should it do
'code' => '', // <------ i dont know what is the logic of this code
]);
}
return response()->json([
'message' => 'operation not successful'
], 500);
}
private function parse_signed_request($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$secret = config('service.facebook.client_secret'); // Use your app secret here
// decode the data
$sig = $this->base64_url_decode($encoded_sig);
$data = json_decode($this->base64_url_decode($payload), true);
// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
private function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
}
what is the URL should do or show.
The purpose of this URL, is what the documentation said - to provide a way for the user, to check on the status of their deletion request.
Not all apps will be able to delete all personal user data immediately, the moment the user requests it.
Some might need to keep a subset of the data for legal reasons; others might simply need some extra processing time, because the process can not be handled in a totally automated matter, and a human needs to get involved.
So the user is given this status check URL in response to their request – so that they can go visit that URL tomorrow, or two weeks or six months from now, and check on the status of their deletion request - were you able to delete all data by now, will it still take some time, is there some data that won’t be deleted for legal reasons, etc.
what is the logic between the confirmation code
Just a different way to access the same information. Maybe checking the status via the URL you provided is not enough for the user, so they might want to call or send an email to your support staff, to inquire about the status of their deletion request. Then they can give your support people that code, and they can go look up the necessary information via that.
If you check the code examples in the documentation, they are using the same code value in the status check URL, and as the confirmation code. So you can use the same code for both.
Create it, store it in your database, and associate the status of a particular user’s deletion request with that code.

Switching FBML to iFrame pageID as request?

We developed a facebook application as tab application using FBML. Now Facebook had deprecated the fbml and we are converting our application to iframe. For this the user can create a FB page and add the application to their facebook page. We are taking the user's facebook page id and check in the DB with this page id and showing the data for that particular user. In the FBML tab application we are getting the facebook page id as a request($REQUEST['page_id']). This seems to no longer work.
When we convert the application to IFRAME tab application, FB is not providing the page id. We are not using GRAPH API and there is any authentication before viewing the application. I had read from a forum that facebook signed request, we will get the page id and used the following code and not getting any data.
$sgrequest = $_REQUEST['signed_request'];
$requestVal = parse_signed_request($sgrequest,$secret);
print_r($requestVal);
$_REQUEST['signed_request']['app_data']
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('vctly987', $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, '-_', '+/'));
}
Is there any other way to get the page id of the fan page through javascript or any other method?
have you tried printing out $requestVal[page][id] after parsing the signed request?
according to the documentation, the signed request contains an array called 'page' that contains the key 'id'. This stores the value of the page's id number.
Can you make sure you enable the migration setting signed_request for Canvas in your App https://developers.facebook.com/apps/.
App Settings -> Advanced

How do i disable the facebook iframe app outside of facebook

I've created a iframe facebook app and i want to disable the app outside of facebook, that the user can't open the app via direct url. I found a solution with javascript, but i need it in PHP.
I can't use the referrer, because some user have disabled it in there browser...
You can check if there's signed_request param sent in request.
If application is opened inside facebook than signed_request exists.
But there's one more issue.
You should check if signed_request is valid and for that you can use parse_signed_request method
public function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = $this->base64_url_decode($encoded_sig);
$data = json_decode($this->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;
}
Then you can check if $data['user_id'] exist or is it equal to logged in user.
If not you can redirect like this
echo "< script type='text/javascript' >top.location.href = '$this->loginUrl'; < /script >";
Or find some way to redirect from php. (There was redirect method in the old php sdk)
Your only real option would be to attempt to use the Facebook API somehow, and see if you get any response.

Basic question regarding Facebook sessions using PHP

So I'm fairly new to Facebook dev and PHP dev so please bare with.
I've created an iframe Facebook application. I have no trouble grabbing a signed request and using that information to do basic tasks on my page.
The real problem happens when I start navigating around my application within Facebook. I seem to lose my signed request information.
I have my PHP code included on every page and I still can't retain my signed request or session.... whatever its called.
I've pasted my basic PHP code below.
<?php
include_once "../lib/facebook.php";
$facebook = new Facebook(array(
"appId" => FACEBOOK_APP_ID,
"secret" => FACEBOOK_SECRET_KEY,
"cookie" => true,
"domain" => SERVER_DOMAIN
));
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, "-_", "+/"));
}
session_start();
if (isset($_SESSION['fb_data'])) {
$data = $_SESSION['fb_data'];
} else {
$data = parse_signed_request($_REQUEST["signed_request"], FACEBOOK_SECRET_KEY);
$_SESSION['fb_data'] = $data;
}
session_write_close();
$page_id = $data["page"]["id"];
$like_status = $data["page"]["liked"];
?>
The signed_request is only passed into your page when it is first loaded as a Facebook Canvas page. The signed_request is passed in as a POST variable. If you are navigating to different pages at the iframe level instead of the top level, you will lose that signed_request parameter.
For example, when user loads this page:
http://apps.facebook.com/test_app/
Facebook will load this inside its IFrame:
http://yourserver.com/test_app/
while passing in signed_request as a POST variable.
If you then navigate to different pages using the following tag:
Page 2
signed_request parameter will be lost.
Instead, you can either pass through the signed_request parameter as a GET variable:
Page 2
Or reload the page at top level:
<a target="_top" href="http://apps.facebook.com/test_app/page2"> Page 2 </a>
In case someone stumbles on this, the latest version of Facebook's php-sdk automatically uses $_SESSION variables to persist the signed_request when it isn't passed in on a Canvas page or Tab request. https://github.com/facebook/php-sdk

Facebook user deauthorizes the app

when user accepts the facebook application from my website, I am storing the user details and facebook details(access token) in database.
when he removes my application from facebook i want to remove the detail from database. how to do this?
I can give Deauthorize Callback url. if some one removes application, it will redirect to this page. but, wt should be the code here to delete the data from db? I means, when it redirect, will it post the access token details, so that i can charge fro access token and delete that row.
It's clearly stated in the authentication document:
App Deauthorization
When a user of your app removes it in
the App Dashboard or blocks the app in
the News Feed, your app can be
notified by specifying a Deauthorize
Callback URL in the Developer App.
During app removal we will send an
HTTP POST request containing a single
parameter, signed_request, which
contains the user id (UID) of the user
that just removed your app. You will
not receive an user access token in
this request and all existing user
access tokens will be automatically
expired.
So using the signed_request function on its own docuement:
<?php
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, '-_', '+/'));
}
$result = parse_signed_request($_REQUEST['signed_request'],"APP_SECRET");
$myFile = "deauthorize.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $result["user_id"] . "\n");
fclose($fh);
?>
So all you need to do is get the $result["user_id"] query your DB and remove the record.
P.S: I would recommend adding a new field called active and just deactivate the user instead of removing the record all together.
EDIT:
Facebook will NOT redirect the user to the deauthorize URL! it'll ping it only:
Facebook pings this URL when a user
deauthorizes your app
This code is not working, although it gets called when a user deauthorizes the app the only data passed into the function is a "1" (Tested with test user and my own FB account when app is live)
file_put_contents("test.txt",$fbUserId . " ". print_r($_REQUEST['signed_request']));
in test.txt file " 1"

Categories