Take the 2-minute tour ×

In Ryan's Railscast on Facebook authorization, he adds some Facebook SDK javascript at the end to "degrade facebook client side authorization with server side authorization." However, I do not see the use of it. If we already set up the authorization from the server side using omniauth, why do we have to add the client-side authorization again? What difference does it make?

The referenced javascript code is (From the linked Railscast):

jQuery ->
  $('body').prepend('<div id="fb-root"></div>')

    dataType: 'script'
    cache: true

window.fbAsyncInit = ->

  $('#sign_in').click (e) ->
    FB.login (response) ->
      window.location = '/auth/facebook/callback' if response.authResponse

  $('#sign_out').click (e) ->
    FB.getLoginStatus (response) ->
      FB.logout() if response.authResponse


One of the reasons we need to integrate FB.login authorization with the server-side authorization might be that the Omniauth server-side authorization does NOT work if it's accessed within the Facebook iFrame. If the user accesses the application for the first time, the application must ask for permissions; however, oAuth permission dialog cannot be loaded within the iFrame to prevent clickjacking. Calling FB.login can avoid such problem, because it will show the permission box as a popup(Omniauth popup option will not work).

So now I have a genuine reason to integrate client-side authorization, but the code from Railscasts does not work with my current settings. I've chosen to do it the following way.

Right now, I have the following script in my application.html.erb:

    // Additional JS functions here
    window.fbAsyncInit = function() {
        appId      : <%= ENV['FACEBOOK_KEY'] %>, // App ID
        status     : true, // check login status
        xfbml      : true  // parse XFBML

    // Load the SDK Asynchronously
       if (d.getElementById(id)) {return;}
       js.src = "//connect.facebook.net/en_US/all.js";
       ref.parentNode.insertBefore(js, ref);


And in my view, I have the following link invoking the Facebook log in action:

<%= link_to 'log in with facebook', '/auth/facebook', id: 'fb_log_in_link' %>

I add the following script to the view page where I have the login link.

function login() {
  FB.login(function(response) {
    if (response.authResponse) {
      window.location = '/auth/facebook/callback'

Also, I need to change the link to call the function instead of directing to /auth/facebook/

<%= link_to_function 'log in with facebook', 'login()' %>

Done! The server-side and client-side authorization are fully integrated. Since I was still confused after watching Ryan's Railscast, I want to add a little bit of explanation for those who might be also confused.

The way this works:

  1. Facebook SDK is initailized when the while the page is loaded.
  2. The user clicks the "log in with Facebook" link.
  3. FB.login function is called by the link, and the user goes through all the permissions process (e.g. permission dialog showing up asking for the user's permissions).
  4. Then, the user is directed to /auth/facebook/callback. From routes.rb we have the line match 'auth/:provider/callback', to: 'sessions#create'. Therefore, now the server will either create a new user or simply create a session if the user has already registered before.
  5. Done! The user is logged in.

Merging server-side and client-side authorization has two major advantages: 1. If the user is logged into the application either inside Facebook(via appcenter) he will be logged into the application outside Facebook as well. Vice versa, if the user logs in outside Facebook, he will be logged in automatically if he accesses it within Facebook after. 2. Logging in with /auth/facebook does not work if the user logs in within Facebook iFrame. To prevent clickjacking Facebook prohibits prompting users to auth permissions dialog within Facebook iFrame. The only way to avoid this is to open the dialog in a separate popup, and logging in with FB.login solves the problem.

share|improve this question
client-side auth is a better user experience. Less page reloading, more immersion in your app. –  sevenseacat Feb 19 '13 at 8:41
So we are actually authenticating the user twice, from the server and the client side? –  Maximus S Feb 19 '13 at 8:42

2 Answers 2

up vote 1 down vote accepted

the short answer is - you don't.
you can choose between client side login (via javascript SDK) and server side login using omniauth.
the disadventage of server-side login is overloading the server for a call you can do from the client.
the advantage is that usually the token is longer (3 months token and not 1-2 hours like client side).
i suggest combine the two. use the client side for initial login, once you do that have an async call from the server side for extended token (only if you have to).

share|improve this answer
could you check my update? –  Maximus S Feb 20 '13 at 3:46

It just says,

Facebook provides a JavaScript SDK that we can use to authenticate a user on the client-side so that it doesn’t look to them like they’ve left our application then returned.

It means that this is for the client side understanding that when user returned from the application, it doesn't look like that they have indeed left it.

share|improve this answer
But even if the user leaves the application, his browser still holds the session that was created when he first logged into the application. So why do we need this? –  Maximus S Feb 19 '13 at 8:39
No, when it says leaves the application, it means leaves the facebook application but not our application. What happens is if you have your application opened and also facebook opened then if you leaves facebook then there is no session and so you need client side authentication. This again regains your session. –  My God Feb 19 '13 at 8:51
never mind! It works :) –  Maximus S Feb 20 '13 at 3:57

Your Answer


