Search code examples
javascriptsafarifacebook-graph-apifacebook-iframefacebook-javascript-sdk

Using Facebook Graph API with the JS SDK in a canvas page iFrame in Safari is broken


So I'm trying to use the Graph API with the Facebook JS SDK and I'm getting the following error in Safari:

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

I suspected it had to do with the fact that Safari is very strict with x-domain cookie setting and so I tried it in Firefox with cookie option set to false in FB.init(). I indeed found that I was getting the same error for my FB.api() requests.

FB.init({
  appId:  "<%= app_id %>",
  status: true, // check login status
  // We cannot rely on this cookie being set in an iframe. I found this
  // out because the Graph API was not working in Safari.
  // cookie: true, // enable cookies to allow the server to access the session
  xfbml:  true, // parse XFBML
  channelUrl: window.location.protocol + '//' + window.location.host + '/fb/canvas/channel.html'
});

So I'm wondering... is there a good way to manually set the access_token query parameter in the FB.api() request?

If the FB.init() cookie gets properly set, this is what the FB.api() request parameters look like:

access_token  xxxxxxxxxxxx|1.xxxxxxxxxxxxxxxxxxxxxx__.3600.xxxxxxxxxx-xxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx
callback      FB.ApiServer._callbacks.xxxxxxxxxxxxxxx
pretty        0
sdk           joey

In Safari (or when the cookie FB.init() option is not set) the FB.api() request parameters look like:

callback      FB.ApiServer._callbacks.xxxxxxxxxxxxxxx
pretty        0
sdk           joey

Now... obviously my app has the ability to generate the access_token on the server side... I'm wondering if there's any way I can manually set FB.api() to use my server-side-generated access_token.


Solution

  • Ok I got it to work. I turns out you don't need the FB.init() cookie: true option in order to use FB.api()--you can manually pass the access_token:

    FB.api("/me/apprequests/?access_token="+access_token, function (response) {});
    

    Where access_token is a JS variable that you set server-side on page load. Here is an ERB example:

    <script>
      var access_token = "<%= @access_token %>";
    </script>
    

    And @access_token is the oauth access_token that gets passed to your canvas page in the initial POST request.