santiagoIT
santiagoIT

Reputation: 9431

pass data back to facebook app after authorisation

I am authotizing my app in the following way:

// authorize app!
                $('#authApp').click(function(){
                    var oauth_url = 'https://www.facebook.com/dialog/oauth/';
                    oauth_url += '?client_id=#{app.id}';
                    oauth_url += '&redirect_uri=' + encodeURIComponent('https://www.facebook.com/pages/null/#{fbPageId()}/?sk=app_#{app.id}');
                    oauth_url += '&scope=user_likes,user_photos';
                    oauth_url += '&app_data=7B%27game%27%3A+%27key%27%7D';
                    oauth_url += '&state=sbSbsbSb';

As you can see I am setting the 'state' param as part of the query string. Now when the user authorizes the app he is redirected to the redirect url.

However the data passed in the state parameter is not posted to my app nor is it part of my app's iframe query string. I was expecting to find it as part of the signed request, but no. This is the deserialized signed request posted back after authorisation

{ algorithm: 'HMAC-SHA256',
  expires: 1348927200,
  issued_at: 1348921162,
  oauth_token: 'AAA...',
  page: { id: '490...', liked: true, admin: false },
  user: { country: 'ec', locale: 'en_US', age: { min: 21 } },
  user_id: '1...' }

I do see that the state is included of the parent page's query string. I need to access that parameter from my app (running inside an iframe). I believe that I cannot just access the parent page's window location because of same origin policy restrictions.

I have read through the documentation and searched online. Persisting data across an app authotization needs to be done using the state parameter. However it is nowhere stated how to retrieve that state param once redirected back to your app.

This is from the facebook doc's regarding the state param:

A unique string used to maintain application state between the request and callback. When Facebook redirects the user back to your redirect_uri, this parameter's value will be included in the response. You should use this to protect against Cross-Site Request Forgery.

Am I supposed to get the state data back from the parent's page query string? Or am I doing something wrong?

* EDIT * I am storing the user to user request Id in the state parameter. For example A invites B to participate in the app via a facebook request. Once B authorises the app A needs to be rewarded. So I need to know that B came to the app following A's invitation. Therefore I store the requestId in the state param, so once B has authorised the app I can take appropriate action.

* EDIT 2 (SOLUTION) ** If your redirect_uri is pointing to the Page Tab URL then facebook will NOT send back the state parameter! It will only be sent back if you redirect to the Canvas URL !!!!!

Upvotes: 0

Views: 497

Answers (2)

C3roe
C3roe

Reputation: 96407

Am I supposed to get the state data back from the parent's page query string?

No, not when authenticating within a canvas/page tab app. The only query string parameter that gets passed to your app in this scenario is the content of the app_data parameter.

But you don’t need the state parameter in this scenario – verifying the signed_request is absolutely sufficient, because it’s signed with your app secret, that only you and Facebook know. So that is enough protection against “manipulated” requests right there already.

See https://developers.facebook.com/docs/authentication/canvas/ resp. https://developers.facebook.com/docs/authentication/pagetab/ for more details. (And see how they do not mention the state parameter at all.)

Edit:

I am storing the user to user request Id in the state parameter. For example A invites B to participate in the app via a facebook request. Once B authorises the app A needs to be rewarded. So I need to know that B came to the app following A's invitation. Therefore I store the requestId in the state param, so once B has authorised the app I can take appropriate action.

That’s a misuse of the state parameter … it’s supposed to achieve something completely different (CSRF protection, as the docs say).

While this might work in your scenario – why are you not using the app_data parameter to transmit this piece of information? That’s the designated way of transferring info to canvas/page tab apps.

Upvotes: 1

Todd Chaffee
Todd Chaffee

Reputation: 6824

The Facebook documentation you referenced is a bit confusing. The only thing you should be doing with the state parameter is making sure you are not a victim of CSRF. Facebook's server side authentication flow gives an example of this in PHP. In short, you should be storing the state value in the session and then verifying that the session value is the same as what Facebook passes back to you in the request. The key line in their PHP example is:

if($_SESSION['state'] && ($_SESSION['state'] === $_REQUEST['state'])) {
   // Continue with application logic here because state matches.
   // Otherwise, exit immediately because you're a victim of CSRF!

So back to your problem. From your redirect URL and the response you are getting, it's obvious your app is on a Facebook Page Tab. See the authentication flow for page tabs for how you should be doing this. Note they are not using the state parameter in step 2 and that the state parameter is never mentioned in page tab authentication flow. So even if you wanted to use the state parameter for something other than its intended use, you are out of luck.

Based on your edits, I suggest you check out the documentation on requests. Note that the user clicking on the request will be redirected to your canvas app, not the page tab. "The canvas URL will also contain an additional GET parameter request_ids, which is a comma delimited list delimited list of Request IDs that a user is trying to act upon." So there is no need for you to be trying to do this yourself.

Upvotes: 1

Related Questions