Skip to content

Instantly share code, notes, and snippets.

@toretore
Created April 9, 2011 23:23
Show Gist options
  • Save toretore/911886 to your computer and use it in GitHub Desktop.
Save toretore/911886 to your computer and use it in GitHub Desktop.
Facebook Canvas apps, CSRF protection & session cookies
Facebook Canvas apps are loaded like this:
* User clicks link to app or tab ("page as tab")
* An iframe is inserted which loads content from the FB server (NOT yours, yet)
Something along the lines of:
<iframe src="http://facebook.com/page_proxy.php?appid=123">
* The FB server returns some HTML & JS with an automatically submitting form:
<form id="humbaba" target="http://you.com/facebook">
<input type="hidden" name="signed_request"/></form>
<script>
//signed_request value, etc are inserted into the form
$('humbaba').submit();
</script>
* Browser (not FB) sends POST request to your app's endpoint URI:
POST http://you.com/facebook
* Your app responds to this request, and the result is shown in the iframe
Apparently, the reasons for doing a POST like this instead of a simple GET (with src="yourapp") is that third-party
resources loaded from inside the iframe would get access to the signed request parameter containing user information
from the referer header, and (noted with what I perceive as a slightly euphemistic tone) "the only other option was for
us to encrypt the UID and that [proved] even more challenging for a great number of devs":
http://developers.facebook.com/docs/canvas/post/
PROBLEM
The form (obviously) doesn't include the CSRF token, and the session gets reset:
https://github.com/rails/rails/blob/v3.0.5/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L97
This can manifest itself in weird ways. Like if your app is accessible outside Facebook and you're logged in, as
soon as you open the app from within Facebook you're logged out.
SOLUTION
Disable CSRF protection for the actions that respond directly to this FB-initiated request. Obviously you
should be certain that this is safe before doing so.
#...
match 'facebook' => 'whatever#humbaba'
#...
class WhateverController < ApplicationController
skip_before_filter :verify_authenticity_token, :only => [:humbaba]
#Facebook Canvas/Tab endpoint routes to here
#POST /facebook
def humbaba
#Render Facebook content
end
end
@brauliobo
Copy link

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment