14

Using Facebook's Graph API, I've been successful at publishing to a user's feed while the user is offline with only the publish_stream permission. I don't need the offline_access permission. I explained how I did this here: Facebook Stream Publish while offline

I haven't been as successful with publishing to a Page while the user is offine. Here's my scenario:

User U is an admin of Page P. P authorizes and installs my app. U authorizes my app and grants me the following extended permissions:

  • publish_stream
  • manage_pages

Once the user is offline, if I try the same technique I use to publish to a user's stream (without offline_access permission) to instead publish to a Page, I get a "The user hasn't authorized the application to perform this action". Here's the technique:

1) fetch my app's access_token

2) use my app's access_token to publish to Page P's feed: POST https://graph.facebook.com/{page_id}/feed

If instead of {page_id} in step 2, I use {user_id}, then it publishes to the user's feed without any problem. However, I'd like to publish to the Page's feed. Is it possible to do this? Or do I need the offline_access permission from the user in order to do this?

Thanks, Johnny

Community
  • 1
  • 1
Johnny Oshika
  • 54,741
  • 40
  • 181
  • 275
  • Are you just trying to write to their wall? Basically, if you are trying to do something on their behalf it requires their premission... (if offline then offline access is required)... It all depends on how you are trying to publish to their feed... – CarpeNoctumDC Mar 09 '11 at 08:32
  • - Per your updated question (btw, that drastically changes the question..) The answer is no. When the user is offline you cannot publish on their behalf without the offline_access permission.. (for security reasons) – CarpeNoctumDC Aug 04 '11 at 02:09
  • 1
    CarpeNoctumDC, that's incorrect. You can publish to a user's stream while the user is offline as long as you have the publish_stream permission. You don't need the offline_access permission. It's explicitly stated in Facebook's documentation (http://developers.facebook.com/docs/reference/api/permissions/ , see publish_stream section) and I've tested it and it works. I was hoping I could publish to the Page stream with the same technique, but it doesn't seem to be the case. To publish to a Page stream while the user is offline, you need the offline_access permission. – Johnny Oshika Aug 19 '11 at 05:37

3 Answers3

7

Full flow - four page example (easier to edit and understand for an example)

So the config just has the basic app info...

When you load index.php - it redirects to facebook to get authorization for the page.. (probably already have this.. but covering all bases)

Facebook then redirects back to the redirecturl (backfromfb.php)...

Facebook returns the access token as a hash and not a get variable, so this page refreshes with the hash as a variable...

It then loads the PageUpdate.php which handles looping through the app/admin tokens and finds the correct one for the page you want to post to..

Then it builds the post and submits it..

It sounds like you have an understanding of most of this... So hopefully this will help you with that last bit.

config.php

<?php
$config = array(
    'appId' => 'YOUR APP ID',
    'secret' => 'YOUR APP SECRET',
    'cookie' => true;
    );

$baseurl = 'http://yoursite.com/';
$returnpage = 'backfromfb.php';

require_once('library/facebook.php');

?>

index.php

<?php require_once('config.php'); ?>

<html><head><title>Redirecting for auth</title></head><body><script type="text/javascript">
            window.location.href = 'https://www.facebook.com/dialog/oauth?client_id=<?php echo $config['appId']; ?>&redirect_uri=<?php echo $baseurl . $returnpage; ?>&scope=manage_pages&response_type=token';
</script></body></html>

backfromfb.php

<?php
require_once('config.php');
// this page just passes the access token from the hash to a GET arg...
if (!isset($_GET['access_token'])) {
?>
<html><head><title>Redirecting</title></head><body><script type="text/javascript">
            accessToken = window.location.hash.substring(1);
            window.location.href = '<?php echo $baseurl . $returnpage; ?>?' + accessToken;
</script></body></html>
<?php
} else {
require_once('PageUpdate.php');
} ?>

PageUpdate.php

<?php
require_once('config.php');

$pageID = "123456 WHatever you page id is";

$AppToken = array(
    'access_token' =>  $_REQUEST['acess_token']
);

$fb = new Facebook($config);

// Load APP page access rights for user via AppToken
$pageAdmin = $fb->api('/me/accounts', 'GET', $AppToken);

// Find the page access token
foreach ($pageAdmin['data'] as $data) {
    if ($data['id'] == $pageID) {
        $pageToken['access_token'] = $data['access_token'];
        continue;
    }
}

// compile the post
$WallPost = array(
    'message' => 'Test post from my app!'
);  // you can also use 'picture', 'link', 'name', 'caption', 'description', 'source'.... 
    //http://developers.facebook.com/docs/reference/api/


// post to wall
$response = $fb->api($pageID . '/feed','POST',$WallPost);

if($response) {

    echo 'Success!';
    echo '<pre>' . $response . '</pre>';

} else echo "failed";


?>
sakibmoon
  • 2,026
  • 3
  • 22
  • 32
CarpeNoctumDC
  • 1,760
  • 1
  • 12
  • 16
  • I probably wasn't very clear in my question, so I updated it a bit. I'm looking to publish to a Page while a user is offline. I'm able to publish to the user's wall while s/he is offline (without the offline_access permission). I'm trying to do the same for publishing to a Page while the user is offline. This can easily be done with the offline_access permission, but I'm wondering if it can be done without it. Thanks for your help. – Johnny Oshika Mar 08 '11 at 14:27
  • Hi, this was absolutely a lifesaver. Just three (minor) additions for future readers - remember of course to include the Facebook SDK and to add the page token you build into the message. Finally change the method from GET to POST if you want to write to the wall. Also in backfromfb.php you need to change the window location to $baseurl . $returnpage; – Andy Aug 03 '11 at 15:30
  • @Andy... Thanks! Updated the code per your suggestions... LMAO I was looking for these files to email someone... forgot I posted them on here.. So double thanks! – CarpeNoctumDC Aug 04 '11 at 02:03
  • @CarpeNoctumDC cool man (just remember to pass the token when posting). Also for future reference to go fully offline it's possible to store the token and in subsequent attempts to post use it. The code as it stands assumes you are logged in (which is necessary to get the token the first time). Thanks again, your code helped me get to the solution :) – Andy Aug 04 '11 at 08:23
  • Thanks this is great, got it to work with this code. However, I wonder how when you post to the page it'll make the post as the page so that it'll show up on everyones news feed? – Jonathan Sep 24 '11 at 23:55
  • @Jonny It finds the $pageID / Page Token so that it can post as the page... So in the PageUpdate.php file you should just need to specify the $pageID to get it to post as a page... – CarpeNoctumDC Sep 27 '11 at 00:38
  • I got a similar code running but for some reason it seems that the page token gets invalidated after a while, any idea? – Claude Vedovini Nov 13 '11 at 17:45
  • @Claude: The app is requesting preimission via the users premissions to access the page. If the user is no longer an admin of the page, the page access would be unavalible/invalidated. As this is a "users" premission and not a "page" premission, you have to query the users access to find the page token. Because of the potential changes in "page" premissions, page tokens are short lived. (As are users access tokens without the "offline_access" premission) If you are requesting offline access, store the user token and page id, then query for the page access token each time you need it – CarpeNoctumDC Nov 16 '11 at 22:53
2

The problem is you need to use the access token for the page provided via the premissions gained...

Uh... Easier way to say it is this:

Your app requested premission to "manage_pages" - once you accept/grant premission then you have an access_token for the apps premission (offline would just make expires=0 here)

So now your app has premission to manage your pages, but it needs the token for the specific page...

So if you issue a /me/accounts (or /UID/accounts) with the first token you will get a list of the pages the application has premission to access and their respective tokens...

From there just grab the token of the page and then issue your command with that token

Using the facebook class (facebook.php and cert file)

require_once 'library/facebook.php';

$app_id = "YOURAPPID";
$app_secret = "YOURSECRET";

$facebook = new Facebook(array(
    'appId' => $app_id,
    'secret' => $app_secret,
    'cookie' => true
));

$token =  array(
    'access_token' => 'THE Token from app / manage_page auth'
);

$userdata = $facebook->api('/me/accounts', 'GET', $token);

echo '<pre'>;
print_r($userdata);
echo '</pre>';

You should see a llist of page id's and their access tokens...

Usuually i do a foreach $userdata['data'] and look for the page id, then i grab the token from that subarray...

sakibmoon
  • 2,026
  • 3
  • 22
  • 32
CarpeNoctumDC
  • 1,760
  • 1
  • 12
  • 16
  • If that has you confused or you need a more in depth example, i could whip up one or two pages to show you more detail... – CarpeNoctumDC Mar 08 '11 at 00:07
  • Thanks. But I think your technique still requires the users's offline_access permission. I don't believe I'll be able to fetch the Page's access tokens (using '/me/account') when the user is offline, because without the offline_access permission, I won't have a valid user access_token. – Johnny Oshika Mar 08 '11 at 14:24
  • Now that Facebook has deprecated the offline_access permission in favor of a long lasting access token, your answer is now correct. :-) – Johnny Oshika Jun 29 '12 at 21:34
1

This is my answer. Above code does not work for me. But I made one for myself, that works perfectly. Here is the code.

Code for server side:

<?php
@session_start();
require "fblib/facebook.php";
define('YOUR_APP_ID','');
define('YOUR_APP_SECRET','');
$facebook = new Facebook(array(
    'appId'  => YOUR_APP_ID,
    'secret' => YOUR_APP_SECRET,
));

if($_SESSION['access_token']!='') {
    $access_token = $_SESSION['access_token'];
$user_id = $_SESSION['user_id'];
} else {
    $access_token = $_REQUEST['access_token'];
    $_SESSION['access_token'] = $_REQUEST['access_token'];
    $user_id = $_REQUEST['user_id'];
    $_SESSION['user_id'] = $_REQUEST['user_id'];
}

$user_id = $_REQUEST['user_id'];

$facebook->setAccessToken($_REQUEST['access_token']);

$post =  array(
    'message' => 'This message is posted with access token - ' . date('Y-m-d H:i:s')
);

// and make the request
$response = $facebook->api('/me/feed', 'POST', $post);
?>

Code for client side:

<?php
require "fblib/facebook.php";
define('YOUR_APP_ID','387647494631464');
define('YOUR_APP_SECRET','857f41bdd23c26ae132a1c75a343ddc9');
$facebook = new Facebook(array(
    'appId'  => YOUR_APP_ID,
    'secret' => YOUR_APP_SECRET,
));

$user = $facebook->getUser();
if ($user) {
    try {
        $user_profile = $facebook->api('/me');
    } catch (FacebookApiException $e) {
        // The access token we have is not valid
        $user = null;
    }
}
?>
<div id="fb-root"></div>
<script language="javascript" src="js/jquery-1.7.2.min.js"></script> 
<script>
    var accessToken;
    var uid;
    // Load the SDK Asynchronously
    (function(d){
        var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
        if (d.getElementById(id)) {
            return;
        }
        js = d.createElement('script'); 
        js.id = id; 
        js.async = true;
        js.src = "//connect.facebook.net/en_US/all.js";
        ref.parentNode.insertBefore(js, ref);
    }(document));

    // Init the SDK upon load
    window.fbAsyncInit = function() {
        FB.init({
            appId      : '', // App ID
            channelUrl : '//'+window.location.hostname+'/channel', // Path to your Channel File
            status     : true, // check login status
            cookie     : true, // enable cookies to allow the server to access the session
            xfbml      : true  // parse XFBML
        });

        // listen for and handle auth.statusChange events
        FB.Event.subscribe('auth.statusChange', function(response) {
            if (response.authResponse) {
                // user has auth'd your app and is logged into Facebook
                FB.api('/me', function(me) {
                    if (me.name) {
                        //   document.getElementById('auth-displayname').innerHTML = me.name;
                        accessToken = response.authResponse.accessToken;
                        uid = response.authResponse.userID;
                    }
                })
                //  document.getElementById('auth-loggedout').style.display = 'none';
                //  document.getElementById('auth-loggedin').style.display = 'block';
            } else {
                // user has not auth'd your app, or is not logged into Facebook
                // document.getElementById('auth-loggedout').style.display = 'block';
                // document.getElementById('auth-loggedin').style.display = 'none';
            }
        });

        // respond to clicks on the login and logout links
        document.getElementById('auth-loginlink').addEventListener('click', function() {
            // FB.login();
            FB.login(function(response) {
                // handle the response
            }, {scope: 'offline_access,publish_stream'});
        });
    }

    function gettoken() {
        //  alert("User Token :"+accessToken+", User id :"+uid);          
        $.post('fbpost.php',{access_token:accessToken,user_id:uid},function(data) {
            //  alert(data);
        });
    }
</script>
<?php if (!$user): ?>
    <a href="Javascript:void(0)" id="auth-loginlink">Login with Facebook</a>
<?php else: ?>
    <a href="Javascript:void(0)" id="auth-logoutlink" onClick="FB.logout()" >Logout from Facebook</a>
<?php endif ?>
<a href="Javascript:void(0)"  onclick="gettoken()" >Post Into Wall</a>

Please disable "Remove offline_access permission:" from fb apps advance setting. by selecting disable radio button.

sakibmoon
  • 2,026
  • 3
  • 22
  • 32
  • 1
    This looks like a post to your own feed (me/feed). I think the OP is asking how to post to a Page, aka Fan Page (PAGE_ID/feed') – Jeff S. Jul 24 '13 at 06:57