So one of the most annoying issues I’ve run into so far (and I’ve got several to choose from here…) in writing a Facebook app for Kongregate is that by default, Safari will not accept any cookies from iFrames that are external to the site in the location bar. Needless to say, this is a problem for Facebook apps that use iFrames. There are several ways of tackling this problem. As soon as a user clicks a link in your app, you get a cookie (yay!), so if you only need state in a limited number of places on your app’s initial (canvas) page, or you don’t need it at all, you can get away with storing it in the params and passing it on to any links the user clicks.
For us, that didn’t work – we need to setup a full session as soon as the user comes to the page. Thus, the only work around is to check and see if we can store a cookie, and if not, then render a lightbox that prompts the user to click the link (and then we get a cookie).
So first of all, we only need to do this check when Facebook renders our page as a callback. So, we look for any of the parameters included in a callback, and if we see them, then we do an AJAX request to check for cookies. Note that we render the partial for the lightbox first (that way we have a chance to store those parameters since we won’t have a way to get them if no session is stored).
<%if params[:fb_sig_session_key] && params[:fb_sig_user]%> <%= stylesheet_link_tag 'lightbox' %> <%= render :partial => 'safari_click_to_store_overlay'%> <script type="text/javascript"> Event.observe(window, 'load', check_session, false) function check_session() { <%= remote_function :url => {:controller => "facebook", :action => "check_session"}, :failure => %(Element.show('lightbox');) %> } </script> <%end -%>
That calls the following method:
def check_session if session[:facebook_session].blank? render :nothing => true, :status => 404 else render :nothing => true end end
So if we got a cookie, we should still have the facebook session data that gets stored in a before_filter set for our facebook app (the before_filter is skipped for check_session). Otherwise, the 404 will trigger the :failure in our javascript above, which renders a (really ugly) lightbox with a link at the bottom that passes along the parameters to associate with our new cookie in the aforementioned before filter:
<%= link_to "Click Here to Continue", facebook_index_path(:fb_sig_session_key => params[:fb_sig_session_key], :fb_sig_user => params[:fb_sig_user]) %>
Update: I came up with a better solution that requires no user interaction.
March 18, 2008 at 10:06 am
I know this post is old, but I just had the exact same problem with a facebook application needed cookie, and finally came with another solution.
My solution is to check if cookies have been set (using an ajax call for example) and if not, to send the whole browser (not the frame) to a page of your site that will set the cookies and then redirect to the facebook canvas page. You can do this by using javascript:
top.location.href = “your_page?all_the_facebook_querystring_here”;
I think this is more elegant because it doesn’t need any user interaction.
March 18, 2008 at 10:24 am
So your solution requires a double redirect?
March 24, 2008 at 7:03 am
Yes, but only once per session in order to set cookies.
By the way you can just check for cookies by using document.cookie in js. I never use cookies in javascript and didn’t figured it out before.
March 24, 2008 at 7:35 am
Simon,
I just noticed that I don’t have a link here to the followup post to this one. Basically, I didn’t like the user interaction thing either so I came up with a way to do without (it doesn’t need a redirect, either). Check it out:
http://wcrawford.org/2007/08/29/revisited-facebook-safari-and-external-iframes-that-need-cookies/
.wc
August 17, 2008 at 6:32 am
Cd4313…
Cd4313…
January 5, 2009 at 10:29 am
[...] Using Expternal iframes in Facebook app, bug resoled [...]
February 9, 2010 at 12:34 am
Hi, Really likes this post. This is test comment to your blog.