Skip to content

Instantly share code, notes, and snippets.

@nontone
Last active September 14, 2016 10:52
Show Gist options
  • Save nontone/dd0e7eedd7fe48bc4cbf73ffb265c563 to your computer and use it in GitHub Desktop.
Save nontone/dd0e7eedd7fe48bc4cbf73ffb265c563 to your computer and use it in GitHub Desktop.
Rails Facebook login with Facebook Javascript SDK

story

  • facebook login will give us authentication response like response.authResponse in javascript
  • we just check it exists then redirect to /auth/facebook/callback
  • because we already have this signed request on cookie after we init facebook js sdk
  • but they always asking we pass code param on url like this /auth/facebook/callback?code=xxx
  • I pass code param from response.authResponse.signedRequest but its seems not correct
FB.login (response) ->
  if response.authResponse
    params = $.param(
      code: response.authResponse.signedRequest
    )
    window.location = "/auth/facebook/callback?#{params}"
, {
  scope: "email,public_profile,user_friends"
}

we always get this error if we send code param with url

ERROR -- omniauth: (facebook) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

if we add provider_ignores_state: true on omniauth.rb setup. we gonna use this on development only but no one suggest because it gonna ignore state param from facebook. [security issue]

ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials: OAuth2::Error, :  {"error":{"message":"Invalid verification code format.","type":"OAuthException","code":100,"fbtrace_id":"F8Cr7uPjkHN"}}

after research

  • facebook init didn't work for some reason
  • its seems cookie didn't set after they authenticated
  • thats why they told us failure such as csrf_detected or invalid_credentials
  • omniauth-facebook using code, cookie name like fsbr_XXX for signed request cookie. look at with_authorization_code!

our facebook init (javascript sdk)

FB.init
  appId: gon.facebook_app_client
  status: true
  cookie: true
  xfbml: true
  version: 'v2.5'

solution for now

  • get back to using manually get auth from facebook
  • link to /auth/facebook
  • that's it

thank you for reading this. so, if anyone have better (or correct) solution, please tell me. thank you!

# I got this script from turbolinks compatibility
#
# reed.github.io/turbolinks-compatibility
$ ->
loadFacebookSDK()
bindFacebookEvents() unless window.fbEventsBound
bindFacebookEvents = ->
$(document)
.on('page:fetch', saveFacebookRoot)
.on('page:change', restoreFacebookRoot)
.on('page:load', ->
FB?.XFBML.parse()
)
@fbEventsBound = true
saveFacebookRoot = ->
if $('#fb-root').length
@fbRoot = $('#fb-root').detach()
restoreFacebookRoot = ->
if @fbRoot?
if $('#fb-root').length
$('#fb-root').replaceWith @fbRoot
else
$('body').append @fbRoot
loadFacebookSDK = ->
window.fbAsyncInit = initializeFacebookSDK
$.ajax
type: "GET"
url: "//connect.facebook.net/en_US/sdk.js"
dataType: "script"
cache: true
initializeFacebookSDK = ->
console.log "add facebook app client" if not gon or not gon.facebook_app_client
FB.init
appId: gon.facebook_app_client
status: true
cookie: true
xfbml: true
version: 'v2.5'
# just only snippet
# enable cookie option on facebook init
FB.login (response) ->
if response.authResponse
window.location = "/auth/facebook/callback"
, {
scope: "email,public_profile,user_friends"
}
# disabled cookie option on facebook init
FB.login (response) ->
if response.authResponse
params = $.param(
code: response.authResponse.signedRequest
)
window.location = "/auth/facebook/callback?#{params}"
, {
scope: "email,public_profile,user_friends"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment