Just thought I’d pass on the better solution I’ve come up with for dealing with the Facebook/iFrame/Cookie issue. The major problem with the last solution is, obviously, that it’s annoying to the user – they have to click something just because of some stupid technical issue! There’s also a more minor problem which is we are doing an AJAX request to test for cookies when it can be done for free on the browser. Anyway, I came up with a solution that fixes both of these issues, using javascript. Its a pretty good solution: no peformance drag on the server, no difference in user experience, and no clutter in your application code (its all in the view, baby (well, except for the tiny nessesary bit that carries over the session info into the new cookie)). Basicly, the script tries to store a cookie using the following function:
function Get_Cookie( name ) { var start = document.cookie.indexOf( name + "=" ); var len = start + name.length + 1; if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) { return null; } if ( start == -1 ) return null; var end = document.cookie.indexOf( ";", len ); if ( end == -1 ) end = document.cookie.length; return unescape( document.cookie.substring( len, end ) ); }
Now the fun part. If the above function fails, we want to attatch the session data to the links, but in our case we want to do it as the links load (rather than waiting until the page loads and risking the user clicking prematurely or forcing them to wait). This was achieved using the extremely useful onDOMLoad script, by Aaron Barker (make sure you javascript_include_tag ‘ondomload’ !)
:
var sess_id = "#{session.session_id}"; if(!Get_Cookie('_session_id')) { zelph_onDOMload('a','AddSessionGrabberToLink(theTarget);'); }
Note that we are storing the session id in a variable: we’ll be using this later to pass the session along in the links. Now to be safe, we don’t want to just stick the session the url – that could be secure data in there. Far better to attatch an event handler to the onclick of the link that creates a form with an invisible text field containing the sess_id and then submits it. That is done in the following function, which is the meat of the javascript:
function AddSessionGrabberToLink(link){ //grab the link and stick it as a param. make the new link submit a form that posts the session_id var url = link.href; var url_with_redirect = "#{url_for :action => :grab_session_and_redirect}" + "?redirect_to=" + url; link.onclick = function() { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = url_with_redirect; var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_session_id'); m.setAttribute('value', sess_id); f.appendChild(m); f.submit(); return false; }; }
Finally, we’ve got to actually deal with that session id. We’ll already have a new cookie and session id by the time the user has clicked the link, so rather than try to use the old session, we just find the old session, copy over what we need, and then redirect:
def grab_session_and_redirect oldsession = CGI::Session::ActiveRecordStore::Session.find_by_session_id(params[:_session_id]) session[:facebook_session] = oldsession.data[:facebook_session] session[:user_id] = oldsession.data[:user_id] session[:username] = oldsession.data[:username] session[:ip] = oldsession.data[:ip] redirect_to params[:redirect_to] and return end
The above is the only code that makes it into your controllers. Not too bad, and the user experience is much better!
i’m trying to embed a google map into a facebook application. majority of google maps use call to onload in body tag. Facebook does not support the body tag. Any ideas how to get it to work without using the body tag.
thanks,
Bailey
Baily — I made the decision to use an IFrame for google map integration. Works well and you can’t even tell for my application.
[...] I came up with a better solution that requires no user [...]
Thanks for the initial insight on how to fix the problem. I think we’ve come up with a slightly more elegant solution:
So we check for our session cookie from the layout we use for Facebook. We defined a constant in ApplicationController. If the cookie doesn’t exist then do your form posting trick automatically. (note we don’t check for links and alter them on the page, and instead do this immediately when needed… should be only once per session. when we post to the controller it has sessions off since we already passed in a session_id and set the cookie there and then redirect to the initial page. Voila Safari iframes, cookie problem fixed.
Again thanks for figuring out the problem!
Inside your layout do:
if (document.cookie.indexOf(“”) == -1) safariFixSession(“”, “‘fb/cookie’) %>”);
Here’s the js function:
function safariFixSession(sess_id, controller) {
alert(‘no cookie found’);
var url = location.href;
var url_with_redirect = controller + “?redirect_to=” + url;
$$(‘body’)[0].insert(”);
var f = $(‘safariFixSession’)
f.method = ‘POST’;
f.action = url_with_redirect;
var m = document.createElement(‘input’);
m.setAttribute(‘type’, ‘hidden’);
m.setAttribute(‘name’, ‘_session_id’);
m.setAttribute(‘value’, sess_id);
f.appendChild(m);
f.submit();
}
And here’s the controller:
ff
class Fb::CookieController < ApplicationController
session
def index
cookies[COOKIE_NAME] = params[:_session_id]
redirect_to params[:redirect_to] and return
end
end
Shoot sorry, that first JS line needs to be:
if (document.cookie.indexOf(”COOKIE_NAME”) == -1) safariFixSession(”SESSION_ID”, “‘fb/cookie’) %>”);
and remove the alert(”) line
I have tried this solution but I could not make it work. Do you have some sample code to share?
This post is almost a year old. Is there now a standard way of dealing with the facebook-iframe-safari-cookie issue? Esp. for Rails?
I’ve written this up in more readable form on my blog, here:
http://saizai.livejournal.com/897522.html
Thanks, Jeremy & Will!
[...] your Rails sessions to carry over from page #1 of your iframe application to page #2 and beyond. Will Henderson has a solution when your Rails application uses the ActiveRecord session store, but new Rails [...]
That’s my trackback just above, but the summary doesn’t say enough.
Will’s solution here is good if you’re using ActiveRecord-backed sessions, but newly generated Rails apps prefer using the cookie store. His trick won’t work for that, as there is no database row, so no row ID, so nothing to pass between the landing page and the rest of the iframe app.
I describe a way to preserve Facebook’s fb_sig parameters through links to the next page, where now Safari will accept cookies since the user has interacted with the iframe.
There is some other stuff in my post that may be of interest to Rails Facebook developers, too.
http://lightyearsoftware.com/blog/2009/11/on-the-pain-of-developing-for-facebook/
Forget slaving away completing jobs on mafia wars for cash. With my mafia wars money cheats, all that becomes childs play. Literally, in 5 minutes, you can have as much cash as you want.
I am so tempted to delete everyone who plays this stuff..it consumes my whole page and I am sure I miss updates I really care about…you should be able to turn off all updates from games..
Myspace poker chips are generally truly like the majority of alternative virtual currencies relating to the internet, just way more fashionable. Zynga poker chips are used throughout virtual texas holdem poker applications found on social networking internet sites by online players just about all over the world anywhere from the United States, to Spain, to Germany. Gamers grind away within the online application after gathering up in distinctive tiered poker rooms which usually are structured according to the number of myspace poker chips they need to buy in. They could have fun at tables having buyins as low as one hundred, 1000, one thousand myspace chips all the way up to 100s of millions and in many cases billions of chips.
Thank you for this post, now ill go on this blog often and check for new articles.
Thank you for this post, now ill go on this blog often and check for new articles.
I want to thank the blogger very much not only for this post but also for his all previous efforts.
I want to thank the blogger very much not only for this post but also for his all previous efforts.
I found your blog when I was searching on yahoo, and it brought me right to what I was looking for. I’m going to add your rss feed to my Google Reader, I look forward to reading more of your thoughts
Awsome stuff … lots of work went in this page. keep it up
I wanna thank the blogger so much not only for this post but also for his all previous efforts.
Thanks for this post..
Why NUVIGIL builds on the success of Modafinil…
General Information on Nuvigil and Provigil I think many of us have already experienced conditions of periodic sleepiness during the day……
Hello, I recently came accross your blog and have been reading along your posts. I decided I will leave my first comment. I have enjoyed reading your blog. Nice blog. I will keep visiting this blog very often…
thanks for the inspiration I was stressed by work but i learnt that life is about living to the fullest and enjoying every moment.Thanks a million
I found the best cheats and stuff at this website
just remember Facebook changes things pretty early so you might need to keep an eye on things when they update.