Sachin Karia
Sachin Karia

Reputation: 565

undefined local variable or method `flash' for #<Devise::OmniauthCallbacksController:0x007fb5d1741e48>

I am building a Rails-API using Omniauth-facebook and Devise-token-auth with Angular and ng-token-auth for the frontend. However when logging in with facebook I am presented with the error:

undefined local variable or method `flash' for #<Devise::OmniauthCallbacksController:0x007fd027a51e10>

It seems omniauth automatically uses flash middleware however the rails-api doesn't include this and I have been unsuccessfully disabling the use of flash with omniauth. My configuration is as below:

application.rb:

    require File.expand_path('../boot', __FILE__)

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module PathfinderApi
  class Application < Rails::Application
    config.active_record.raise_in_transactional_callbacks = true


    config.middleware.insert_before 0, "Rack::Cors" do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :options]
      end
    end

    config.api_only = true
    config.middleware.use ActionDispatch::Flash
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore
  end
end

devise_token_auth.rb:

DeviseTokenAuth.setup do |config|
  Rails.application.secrets.facebook_app_secret
  config.change_headers_on_each_request = true
end

devise.rb:

Devise.setup do |config|
  config.navigational_formats = [:json]
end

omniauth.rb:

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

I have not managed to disable the flash error with:

config.navigational_formats = [:json]

and devise/omniauth is still using flash middleware and throws the error, any help appreciated!

Upvotes: 7

Views: 8881

Answers (5)

Imad EL AZYFY
Imad EL AZYFY

Reputation: 1

Try adding this line to your devise.rb

config.navigational_formats = [ :json ]

Upvotes: 0

titeuff
titeuff

Reputation: 11

I'm turning crazy, I tried everything but after redirection in failure case with omniauth and Devise, flashes still empty.

  • with standard authentication: no problem
  • with omniauth success auth : no problem
rails (6.1.7)
devise (4.8.1)
omniauth (1.9.2)
omniauth-ldap (1.0.5)

My failure method seems correct:

def failure
      set_flash_message(:error, :failure, kind: "LDAP", reason: "invalid_credentials encountered")
      redirect_to root_url, flash: { error: flash[:error] }      
    end

Here it is flash content in failure method

#<ActionDispatch::Flash::FlashHash:0x00007fea79ece8c8 @discard=#<Set: {}>, @flashes={"error"=>"Could not authenticate you from LDAP because invalid_credentials encountered"}, @now=nil>

and here it is flash content just after redirect

#<ActionDispatch::Flash::FlashHash:0x00007fea7a180ad0 @discard=#<Set: {}>, @flashes={}, @now=nil>

Upvotes: 0

Flov
Flov

Reputation: 1587

I managed to solve this by adding this to the devise.rb config:

config.navigational_formats = []

This way devise will never attempt to use flash and never throw a 500 error. Taken from https://github.com/heartcombo/devise/issues/4275

Upvotes: 3

user2990181
user2990181

Reputation: 13

Had the same problem in Rails (5.0.0.1) + devise_token_auth (0.1.39).

Besides the override in @Koen's answer, the following addition is also necessary in my case:

# in config/application.rb
  config.middleware.use ActionDispatch::Cookies

Upvotes: 0

Raymundus
Raymundus

Reputation: 2472

Had the same problem. Searched the devise source code for 'flash'. Found about 17 matches, all using set_flash_message! (with exclamation mark), except for the failure method in the OmniauthCallbacksController, which uses set_flash_message (without exclamation mark). Looking at the definition we see:

\app\controllers\devise\omniauth_callbacks_controller.rb

# Sets flash message if is_flashing_format? equals true
def set_flash_message!(key, kind, options = {})
  if is_flashing_format?
    set_flash_message(key, kind, options)
  end
end

\lib\devise\controllers\helpers.rb

def is_flashing_format?
  is_navigational_format?
end

def is_navigational_format?
  Devise.navigational_formats.include?(request_format)
end

The actual flash message is generated in the method without exclamation mark (I would have progged it the other way around...). The missing exclamation mark is the reason why setting the navigational_formats as mentioned in other solutions doesn't work here.

Conclusion: they forgot the exlamation mark.

The fix: monkey-patch the failure method from the OmniauthCallbacksController. Do this in an initializer, for example in

\config\initializers\devise.rb

Rails.application.config.to_prepare do              # to_prepare ensures that the monkey patching happens before the first request
  Devise::OmniauthCallbacksController.class_eval do # reopen the class
    def failure                                     # redefine the failure method
      set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
      redirect_to after_omniauth_failure_path_for(resource_name)
    end
  end
end

Upvotes: 5

Related Questions