title: How to properly handle session and access token with Facebook PHP SDK 3.0?
body: <p>In the PHP 3.0 SDK there is no <code>getSession()</code> 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 <strong><a href="http://knoopgroup.org/" rel="nofollow noreferrer">this blog entry</a></strong> and <strong><a href="http://bugs.developers.facebook.net/show_bug.cgi?id=18633" rel="nofollow noreferrer">this bug report</a></strong>.</p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>However, I don't know if that really effects my problem. Like in <strong><a href="https://stackoverflow.com/questions/6460531/facebook-session-transfer-js-sdk-to-php-sdk">this question's answer</a></strong> I am retrieving the access token of the OAuth dialog with PHP and save the new access token in the session.</p>
  
  <h2>Current workaround</h2>
  
  <p>The following code shows how I am handling this sessions. <code>$_REQUEST['session']</code> is the content of the response of the OAuth dialog.</p>
  
  <pre><code>if(isset($_REQUEST['session'])) {
  
      $response = json_decode(stripslashes($_REQUEST['session']), true);
  
      if(isset($response['access_token'])) {
          $this-&gt;api-&gt;setAccessToken($response['access_token']);
          $_SESSION['access_token'] = $this-&gt;api-&gt;getAccessToken();
      }
  
  }
  elseif(isset($_SESSION['access_token']) &amp;&amp; ! isset($_REQUEST['signed_request'])) 
      $this-&gt;api-&gt;setAccessToken($_SESSION['access_token']);
  elseif(isset($_REQUEST['signed_request'])) {
      Session::invalidate('fbuser');
      $_SESSION['access_token'] = '';
  }
  </code></pre>
  
  <p>Here is how I handle the user data:</p>
  
  <pre><code>try {
      $this-&gt;user = Session::getVar('fbuser');
      if ($this-&gt;user === false || is_null($this-&gt;user)) {
          $facebookUser = $this-&gt;api-&gt;api('me?fields=id,name,first_name,last_name');
          $this-&gt;user = new FBUserModel(array('fbId' =&gt; $facebookUser['fbId'], ...));
          Session::setVar('fbuser', $this-&gt;user);
      }
  }
  </code></pre>
  
  <p><br /></p>
  
  <h2>The Problem</h2>
  
  <p>Everything looks fine while testing. Only once an error occured: <strong>the first time</strong> after permission was set. Now, since the app is online, it seems as if the error occurs on average with every second user in</p>
  
  <pre><code>$facebookUser = $this-&gt;api-&gt;api('me?fields=id,name,first_name,last_name');
  </code></pre>
  
  <p>with the error:</p>
  
  <pre><code>An active access token must be used to query information about the current user.
  </code></pre>
  
  <p><br /></p>
  
  <h2>Question</h2>
  
  <p>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?</p>
  
  <p>Any help would be highly appreciatied!</p>
  
  <p><br /></p>
  
  <h2>Edit</h2>
  
  <p>I found out that there are some IE issues with cookies/session inside an iFrame. As seen <strong><a href="http://adamyoung.net/IE-Blocking-iFrame-Cookies" rel="nofollow noreferrer">in this blog post</a></strong>. With that hint and some further research I added the following lines in my bootstrap:</p>
  
  <pre><code>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"');
  </code></pre>
  
  <p>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.</p>
  
  <p><br /></p>
  
  <h2>Edit 2</h2>
  
  <p>I edited my user handling from</p>
  
  <pre><code>if ($this-&gt;user === false || is_null($this-&gt;user)) {
      // get user data
  }
  </code></pre>
  
  <p>to</p>
  
  <pre><code>if ((is_object($this-&gt;user) &amp;&amp; $this-&gt;user-&gt;fbId == '') || $this-&gt;user === false || is_null($this-&gt;user)) {
      // get user data
  }
  </code></pre>
  
  <p>This seems to help a little bit. I think the main problem is somewhere in my session.</p>
  
  <p>Furthermore I added a try/catch block to see if somewhere in my app a Facebook <code>OAuthException</code> is thrown. If this is the case, I redirect the <strong>top location</strong> to the Facebook Page and Tab to get a <strong>new signed request</strong>. Though this might help solve this problem, I want to prevent my app from having to redirect the user.</p>
  
  <p><br /></p>
  
  <h2>Edit 3</h2>
  
  <p>After some days of intense debugging and logging I found out, that the <code>$_REQUEST['session']</code> coming from the <strong>FB.ui permissions.request method</strong> is empty infrequently.</p>
  
  <p>Here is how I handle it:</p>
  
  <p>This is the stuff I always included:</p>
  
  <pre><code>FB.provide("UIServer.Methods", {'permissions.request': {size : {width: 575, height: 300}, url: 'connect/uiserver.php', transform : FB.UIServer.genericTransform}});
  </code></pre>
  
  <p>And this function is called on form submit. Always worked for me, but somehow it still sends the form although <code>session == ''</code>.</p>
  
  <pre><code>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' &amp;&amp; info.session !== null) {
              $(session).val(JSON.stringify(info.session));
              form.submit();
          }
      });
      return;
  }
  </code></pre>