How to properly handle session and access token with Facebook PHP SDK 3.0?
Asked Answered
E

5

37

In the PHP 3.0 SDK there is no getSession() or any session handling from outside the Facebook api available. Some days ago the developers of facebook have also somehow updated the JavaScript sdk, according to this blog entry and this bug report.

Within the last few days, a change was introduced into the hosted JS SDK which broke all compatility between it and the current PHP SDK (2.x and 3.x). Developers who utilize both the JS and PHP SDK on their websites are likely to see server-side API failure.

However, I don't know if that really effects my problem. Like in this question's answer I am retrieving the access token of the OAuth dialog with PHP and save the new access token in the session.

Current workaround

The following code shows how I am handling this sessions. $_REQUEST['session'] is the content of the response of the OAuth dialog.

if(isset($_REQUEST['session'])) {

    $response = json_decode(stripslashes($_REQUEST['session']), true);

    if(isset($response['access_token'])) {
        $this->api->setAccessToken($response['access_token']);
        $_SESSION['access_token'] = $this->api->getAccessToken();
    }

}
elseif(isset($_SESSION['access_token']) && ! isset($_REQUEST['signed_request'])) 
    $this->api->setAccessToken($_SESSION['access_token']);
elseif(isset($_REQUEST['signed_request'])) {
    Session::invalidate('fbuser');
    $_SESSION['access_token'] = '';
}

Here is how I handle the user data:

try {
    $this->user = Session::getVar('fbuser');
    if ($this->user === false || is_null($this->user)) {
        $facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');
        $this->user = new FBUserModel(array('fbId' => $facebookUser['fbId'], ...));
        Session::setVar('fbuser', $this->user);
    }
}


The Problem

Everything looks fine while testing. Only once an error occured: the first time after permission was set. Now, since the app is online, it seems as if the error occurs on average with every second user in

$facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');

with the error:

An active access token must be used to query information about the current user.


Question

So why is this happening? It is very hard to debug since the error seems to only occur when a user enters the app the first time, after the app authentication and the access token has changed. And even that is not happening every time. How should I handle the session and access token right with the new PHP SDK?

Any help would be highly appreciatied!


Edit

I found out that there are some IE issues with cookies/session inside an iFrame. As seen in this blog post. With that hint and some further research I added the following lines in my bootstrap:

ini_set('session.use_trans_sid', 1);
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

Now its much better, but the information from about 2 of 50 users get lost between the steps landing page (authentication) -> formular -> and registration. So there is still something I missed.


Edit 2

I edited my user handling from

if ($this->user === false || is_null($this->user)) {
    // get user data
}

to

if ((is_object($this->user) && $this->user->fbId == '') || $this->user === false || is_null($this->user)) {
    // get user data
}

This seems to help a little bit. I think the main problem is somewhere in my session.

Furthermore I added a try/catch block to see if somewhere in my app a Facebook OAuthException is thrown. If this is the case, I redirect the top location to the Facebook Page and Tab to get a new signed request. Though this might help solve this problem, I want to prevent my app from having to redirect the user.


Edit 3

After some days of intense debugging and logging I found out, that the $_REQUEST['session'] coming from the FB.ui permissions.request method is empty infrequently.

Here is how I handle it:

This is the stuff I always included:

FB.provide("UIServer.Methods", {'permissions.request': {size : {width: 575, height: 300}, url: 'connect/uiserver.php', transform : FB.UIServer.genericTransform}});

And this function is called on form submit. Always worked for me, but somehow it still sends the form although session == ''.

function getPermission(form) {

    session = $('#' + $(form).attr('id') + ' input[name="session"]');

    if($(session).val() != '') {
        form.submit();
        return;
    }

    FB.ui({method: "permissions.request", "perms": 'user_photos'}, function callback(info){
        if(info.status=='connected' && info.session !== null) {
            $(session).val(JSON.stringify(info.session));
            form.submit();
        }
    });
    return;
}
Evaleen answered 24/6, 2011 at 12:57 Comment(3)
could you give more information on what your "bootstrap" is and what else it contains?Tenno
@Tenno my bootstrap contains path configurations, auto loader, config, and session handling. The only thing relevant to my problem is what I already posted: the use_trans_sid and the P3P header.Evaleen
+1 for mentioning p3p headers. Those things killed me for weeks when trying to create a Facebook app in ASP.NET.Sworn
E
5

My solution

Well, since everything I did was just a workaround until the new JS SDK comes out, there seems to be no best practice. Setting session.use_trans_sid to 1 and adding the P3P header helped to overcome IE iFrame cookie issues (see my first edit). After a few days of heavy debugging I found out, that FB.ui's permission_request does not send a new access token everytime (<5%).

If this happens, something went wrong. But this little something is driving me crazy. Since this happens infrequently, I can bear redirecting users back to the facebook tab to get a new signed request. With the new JS SDK, hopefully, this won't happen anymore.

Update: final solution

There was one little thing I have overseen and the solution can be found here: FB is not defined problem
I did not load the JS SDK asynchronously! This explains everything. Sometimes the all.js file was not loaded fast enough, so there was a JS error. Due to that, neither the permission dialog nor the JS validation worked and an empty #session input value was sent.

Evaleen answered 14/7, 2011 at 19:2 Comment(1)
Glad you got it sorted! Hopefully, the PHP-SDK will get updated soon so that you'll have your system properly integrated.Lolanthe
M
10

I'm using now PHP SDK 3.x without any problem.

Naitik the class author removed the getSession() function, and now if you want to know if the user is authenticated or not, use getUser().

For Access token, it's very simple, use this function getAccessToken(), and you'll get the access token to make Graph or Rest API calls.

$user = $facebook->getUser();

if ($user) {
//USER Logged-In
}
else {
//USER not Logged-In
}

//TO GET ACCESS TOKEN
$access_token = $facebook->getAccessToken();


//MAKE AN API CALL WITH IT
$user_info = $facebook->api('me?fields=id,name,first_name,last_name&access_token='.$access_token);
Misgiving answered 27/6, 2011 at 8:27 Comment(3)
you didn't understand my problem: I have to get the permission through JavaScript. The PHP 3.x SKD does not communicate well with the currently available JS SDK. The access token is NOT changed automatically. So, I wrote this workaround to save the new access token in the session. And THIS is only working about 95% of the time...not 100%Evaleen
@Sascha Galley - do you really need to get permission only using JS ? using PHP SDK for getting permission should save you from this problem.Propaedeutic
@Sergey Nester: I know, but it is a requirement for this and other projects to use the JS dialog. If there was no possibility at all to combine the old JS with the new PHP SDK I could argue with that. But as already mentioned my workaround is working in >95%. There is only one little thing that keeps me from 100%. I could also catch the error, reload the whole page and get the new signed request, but I want to know why this is happening.Evaleen
E
5

My solution

Well, since everything I did was just a workaround until the new JS SDK comes out, there seems to be no best practice. Setting session.use_trans_sid to 1 and adding the P3P header helped to overcome IE iFrame cookie issues (see my first edit). After a few days of heavy debugging I found out, that FB.ui's permission_request does not send a new access token everytime (<5%).

If this happens, something went wrong. But this little something is driving me crazy. Since this happens infrequently, I can bear redirecting users back to the facebook tab to get a new signed request. With the new JS SDK, hopefully, this won't happen anymore.

Update: final solution

There was one little thing I have overseen and the solution can be found here: FB is not defined problem
I did not load the JS SDK asynchronously! This explains everything. Sometimes the all.js file was not loaded fast enough, so there was a JS error. Due to that, neither the permission dialog nor the JS validation worked and an empty #session input value was sent.

Evaleen answered 14/7, 2011 at 19:2 Comment(1)
Glad you got it sorted! Hopefully, the PHP-SDK will get updated soon so that you'll have your system properly integrated.Lolanthe
R
2

For starters, I would debug a little more. Log the contents of the requests. What’s stored in $_SESSION, what’s passed in $_REQUEST. Also, check if it’s a browser issue (is it happening regardless of the browser, or is there a pattern?)

But since fixing the cookie issue in IE (P3P header) helped, my guess is that there are some browsers left, that deny third party cookies. As far as I know, some versions of Safari and Opera does that by default. In addition, this error states that there was no access_token provided, as opposed to invalid or expired one.

You can test that by disabling third party cookies (using about:config in firefox for instance), deauthorizing your app (using the "Apps and websites" section on the bottom of Facebook Privacy settings), deleting cookies (related to your canvas URL) and then launching the application.

BTW, there’s always a possibility of facebook not returning access token even when it should, as described in bug 17236

Rummage answered 2/7, 2011 at 19:3 Comment(1)
thanks, this is the best answer so far. i will not accept it immediately to let it be open for further research, but I give you the deserved bounty right now. so...stay tuned :)Evaleen
E
1

Hi i've run in the same trouble seems i've solved it with watching the JS API and redirect to the PHP-SDK Login Page if User Information is readable

example:

<script language="JavaScript">

function check_fb_status(){
    FB.api('/me', function(response){
     if(response.name) window.location='<?php echo $facebook->getLoginUrl(); ?>';
     else check_fb_status();
    });
}

check_fb_status();

</script>

if the script succed it loads the loginpage, and user got recognized by both JS and PHP SDK ;)

Elma answered 22/8, 2011 at 0:34 Comment(0)
V
0

FYI, Facebook posted an update to the PHP SDK about 2 hours ago which adds support for the new cookie format, if you're creating a session on the client using the JavaScript SDK. The update can be found at the Facebook PHP-SDK GitHub repo.

Varsity answered 5/8, 2011 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.