I find little else as infuriating as bashing my head against some phantasmal 3rd-party issue which is stopping me from working on something I'm actually interested in.
- Utilizing Facebook’s FB.login() results in a blank popup with the title XD Proxy, and therefore, no callback.
- I’m honestly not 100% sure, but I believe it has something to do with IE8 handling cross domain communication poorly.
- When calling FB.init() make use of a Custom Channel URL
Cross Domain and Custom Channels
As I mentioned before, I’m pretty sure this problem is caused by a security feature of IE8 identifying (and blocking) Facebook’s cross domain request as a potential XSS attack.
Therefore, a potential solution would be to have the FB login request somehow go through our domain, rather than Facebook’s. Luckily, from my limited understanding, that’s exactly what a custom channel URL is.
Essentially, we’ll be hosting a copy of Facebook’s login receiver page on or domain, so that IE8 has no problems with the request, and will subsequently let everything through nice and clean like.
The Custom Channel File
A scary sounding “Custom Channel” is really nothing more than a script tag in a file hosted on your domain. Here’s how to make your own:
- Create an HTML file called “channel.html” containing ONLY AND EXACTLY the following code:
Upload the file to your server and congratulations, you just created a Custom Channel, with ChannelURL: http://example.com/channel.html
We tell Facebook to use a custom channel by passing FB.init() the additional parameter ChannelURL.
You’re going to want your FB.init() call to look something like this:
appId : [APP ID],
status : true,
cookie : true,
xfbml : true,
channelUrl : full_domain + ‘/channel.html’
Why have the variable full_domain? Well, remember, the problem we’re working around is cross domain communication, so the channelURL must be on the same domain as the FB.init() call. Everything must match, from the protocol (http/https) to the subdomain. full_domain is just a string containing the domain as such.
Said another way, if your login button is on https://www.GuiltyGrannies.com then your channelURL should be something like https://www.GuiltyGrannies.com/channel.html.
You can hard-code this URL just fine, but since we’re using the same code on multiple domains, we just opted to make it dynamic instead.
Why I’m An Idiot (Probably)
On the FB.init() documentation page about the parameter channelURL it says this:
This is an option that can help address three specific known issues. First, when auto playing audio/video is involved, the user may hear two streams of audio because the page has been loaded a second time in the background for cross domain communication. Second, if you have frame busting code, then you would see a blank page. Third, this will prevent inclusion of extra hits in your server-side logs.Now, in my defense, I’m not sure exactly what “frame busting” code is, but I suppose I’m doing it somewhere. Or something. I’d normally expect a $50 billion company to have a bit less hand-waving in their public API documentation, but that’s just me.
Other Possible Fixes
In my searching I found a couple of other suggestions in newsgroups and the like for how to fix a couple variations of this problem. Here is a short collection of the ones that seemed to work for some people, but not me:
- Make sure your <div id=”fb-root”> is the first child of Body
- There may be a problem related to your Flash version
- Check to make sure that IE isn’t in some weird protected mode
- If you’re developing locally, make sure IE doesn’t have you in any special security zones
I hope this managed to help someone out there, because holy hell was this annoying. But all’s well that ends well.
God speed, and happy coding!