28

I am trying to implement omniauth-facebook as described in Railscast #360 and have run into quite a roadblock. When I click on the signin link, I get the desired popup asking me to input my facebook credentials, but when I submit, I get an OmniAuth::Strategies::OAuth2::CallbackError error. In the apache logs, this is printed: (facebook) Authentication failure! invalid_credentials: OmniAuth::Strategies::OAuth2::CallbackError, OmniAuth::Strategies::OAuth2::CallbackError

here is the relevant code:

omniauth.rb

OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
end

sessions_controller.rb

class SessionsController < ApplicationController
  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = user.id
    redirect_to root_url
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_url
  end
end

application.html.erb

<div id="fb-root"></div>
<script>        
window.fbAsyncInit = function() {
    FB.init({
        appId      : '(**my app id**)', // App ID
        status     : true, // check login status
        cookie     : true // enable cookies to allow the server to access the session
    });

    $('#sign_in').click(function(e) {
        e.preventDefault();
        return FB.login(function(response) {
            if (response.authResponse) {
                return window.location = '/auth/facebook/callback';
            }
        });
    });

    return $('#sign_out').click(function(e) {
        FB.getLoginStatus(function(response) {
            if (response.authResponse) {
                return FB.logout();
            }
        });
        return true;
    });
};
 </script>

Am I missing something simple? I've been searching for a solution for the last few days.

petfreshman
  • 513
  • 2
  • 8
  • 21

7 Answers7

68

It seems like omniauth-facebook v1.4.1 introduced an issue with CSRF. A temporary fix is to just roll back to v1.4.0. In your Gemfile, change the omniauth-facebook line to:

gem 'omniauth-facebook', '1.4.0'

I've reported the issue: https://github.com/mkdynamic/omniauth-facebook/issues/73

Tom Söderlund
  • 4,743
  • 4
  • 45
  • 67
  • 6
    Tom you have put an end to days of frustration. There's a little clean up work to do but that simple solution fixed the issue. Thanks so much for looking into this! – petfreshman Jul 24 '12 at 03:07
  • 4
    Excellent! God love you--and stackoverflow. – Steve Upstill Apr 10 '13 at 23:07
  • Note that this is not a real solution. Requiring the state parameter to be there is (currently) the only solution to prevent CSRF through oauth. So at some point this issue has to be addressed. Unfortunately not all providers return the state param and in some cases its even abused for internal functionality. So this will stay interesting. – wrtsprt May 14 '13 at 06:52
  • you saved my day. Ryan Bates must update his post in railscast – Arnaldo Ignacio Gaspar Véjar Jul 23 '13 at 17:28
  • There's a 'provider_ignores_state' option so you don't have to downgrade: https://github.com/intridea/omniauth-oauth2/issues/32 – Ponny Aug 20 '13 at 21:51
6

I had a similar issue where it was working for 1 user but getting the Authenticating error for the 2nd user.

Disabling the Sandbox mode (Apps > Settings > Advanced) seems to have fixed it.

Pragnesh Vaghela
  • 1,327
  • 12
  • 16
1

In your omniauth.rb add code:

OmniAuth.config.on_failure = Proc.new do |env| new_path = "/auth/failure"
 [302, {'Location' => new_path, 'Content-Type'=> 'text/html'}, []]
end
Tiago
  • 2,156
  • 2
  • 18
  • 27
1

I've noticed that omniauth-oauth2 > 1.0.3 will cause a problem too, uninstalling higher version and keep omniauth-oauth2 1.0.3 solved the problem ..

simo
  • 23,342
  • 38
  • 121
  • 218
0

I have this too.

Remove the JS script in your application.html.erb (but keep the fb-root div) will work. Anyway, the FB login screen won't be displayed in a popup window anymore, you'll be redirected to FB login then back to your site instead.

JNN
  • 947
  • 10
  • 19
  • 1
    The reason I have it in a script is so that I can have the popup. I don't want my users to redirect away from my site. – petfreshman Jul 23 '12 at 15:05
0

For anyone that's careless like I am,

Remember to switch you app out of Sandbox mode at developers.facebook before you deploy!

Sandbox mode will trigger the csrf error for everyone except the developer's account.

umezo
  • 1,519
  • 1
  • 19
  • 33
0

you may want to override OmniauthCallbacksController, and add this to logging:

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def failure_message
    exception = env["omniauth.error"]
    #add login here:
    Rails.logger.info "exception: #{exception.inspect}"
    error   = exception.error_reason if exception.respond_to?(:error_reason)
    error ||= exception.error        if exception.respond_to?(:error)
    error ||= env["omniauth.error.type"].to_s
    error.to_s.humanize if error
  end

  #other code ...
end

after ive added mine, i found "invalid ip..." issue,

James Tan
  • 1,336
  • 1
  • 14
  • 32