Search code examples
ruby-on-railsfacebookdeviseomniauthomniauth-facebook

CSRF Detection fix provider_ignores_state: true not saving session after successful Devise Omniauth-Facebook Authentication


My application was working ok, and then I updated to Rails 5.0.1. After this my app no longer authenticated with Facebook and came up with the following error in the logs:

Authentication failure! csrf_detected: 
OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

So, in accordance to what people on StackOverflow suggested, I changed my omniauth config to include the provider_ignores_state: true setting, which suppressed that error.

config.omniauth :facebook, 'xxx', 'xxxxxxxxxxxxx',{
      scope: 'public_profile,email,user_birthday,etc...',
      info_fields: 'name,first_name,etc...',
      provider_ignores_state: true
  }

This made everything work just fine; at least in development running locally, but when I pushed the code to my staging server, the app successfully authenticates with Facebook, supposedly "signs" the user in and redirects to root_path() - and then fails authentication and redirects back to users/sign_in.

To help diagnose the problem i put a logging line above the relevant call (to see if it was being executed) such as:

logger.debug "  (OmniauthCallbacksController#facebook) about to sign_in_and_redirect with id: #{@user.id} email: #{@user.email} uid: #{@user.provider_uid}"
sign_in_and_redirect @user, event: :authentication

My OmniauthCallbacksController handler for the Facebook provider there for does seem to reach 'sign_in_and_redirect' - but for reasons I cannot determine on my staging environment, it never actually saves the session to a cookie. There are no errors in the logs (in debug mode) to demonstrate there was any kind of exception thrown - except that the query to increment the log_in_count on the user doesn't actually run any query:

(2.4ms)  COMMIT
(0.2ms)  BEGIN
(0.2ms)  COMMIT

Which looks weird (no actual update query, whereas in development i can see the log_in_count etc be incremented). But its the only other indication that something goes wrong. After that, it fails the authenticate_user! check and redirects back to the sign_in_url.

This is sending me mad - Is this a bug, or is there a fix for this issue?


Solution

  • I was finally able to solve this issue, but I still don't understand WHAT went wrong. Basically, created a "empty" Rails 5 project and setup a brand new devise using the omniauth-facebook gem and settings for my main app - deployed to a cloned instance of the staging server and it worked! Most of the code was the same; but when I replaced the devise.rb initializer with the one from the new app, the old code proceeded to work on the stagingg server again. Interestingly, I coped the Omniauth config from the old one to the new app, so it must have been something wrong with another of Devise's modules...and not with Omniauth itself.

    In either case, it's working now. So I will put this to bed and leave this here in case another person encounters the same problem; and while I cant say what was specifically wrong, these are the steps I used to debug/fix my particular problem.