ruby-on-railsdeviseomniauth

OmniAuth::NoSessionError - You must provide a session to use OmniAuth. (configured in devise)


Hi I am learning how to use omniauth as backend for ember app.

when i run my application I get the below mentioned erroe OmniAuth::NoSessionError - You must provide a session to use OmniAuth

on resue rails s my applicataion halts at line below.

  172: def call!(env) # rubocop:disable CyclomaticComplexity
    173:   unless env['rack.session']
    174:     error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
 => 175:     fail(error)
    176:   end
    177: 

config/intializer/devise

Devise.setup do |config|

  config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
  require 'devise/orm/active_record'
  config.case_insensitive_keys = [ :email ]
  config.strip_whitespace_keys = [ :email ]
  config.http_authenticatable = true
  config.skip_session_storage = [:http_auth]
  config.stretches = Rails.env.test? ? 1 : 10
  config.reconfirmable = true
  config.expire_all_remember_me_on_sign_out = true
  config.password_length = 8..128
  config.reset_password_within = 6.hours
  config.http_authenticatable_on_xhr = false
  config.navigational_formats = ['*/*', :html,:json]
  config.sign_out_via = :delete
  require 'omniauth-facebook'
  config.omniauth :facebook, ENV['8987087080'] , ENV['3d6a359a37c8780870dxxxx5'],:strategy_class => OmniAuth::Strategies::Facebook
end

config/intializer/session_store.rb

Rails.application.config.session_store :disabled

routes.rb

Rails.application.routes.draw do

  namespace :api do
    namespace :v1 do
      resources :users
      resources :games
    end
  end

  ActiveAdmin.routes(self)
  #devise_for :admin_users, ActiveAdmin::Devise.config
  devise_for :users, controllers: { 
    omniauth_callbacks: 'omniauth_callbacks',
    sessions: 'sessions' , 
    registrations: "registrations",


  }
   devise_scope :user do 
    match 'users/sign_in', to: 'sessions#create', via: :post
    match 'api/v1/users' , to: 'registrations#create' , via: :post
  end

end

gemfile.rb

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.6'

platforms :ruby do # linux
  gem 'unicorn'
  gem 'foreman'
  gem 'delayed_job_active_record'
end
group :development, :test do
    gem 'compass'
    gem 'pry'
    gem 'pry-remote'
    gem 'pry-rails'
    gem 'pry-rescue'
    gem 'pry-stack_explorer'
    gem 'pry-byebug'
    gem 'guard'
    gem 'guard-livereload'
    gem 'guard-rails'
    gem 'guard-rspec'
    gem 'guard-cucumber'
    gem 'guard-zeus'
    gem 'rspec-rails'

end
group :production do
    #gem 'pg'
end

#authentication
gem 'cancan'
gem 'rolify'
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook', '=1.4.0'
gem 'oauth2'



# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0'
gem 'bootstrap-sass', '~> 3.1.1'
gem 'bootswatch-rails'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'



# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'


group :doc do
  # bundle exec rake doc:rails generates the API under doc/api.
  gem 'sdoc', require: false
end

#ember
gem "active_model_serializers"
gem "ember-source", "~>1.7.0"

#asyc http calls
gem 'hashie_rails'
gem "typhoeus"
gem "virtus"

#middleware
gem "rack-cors", require: 'rack/cors'



platforms :mswin do 
  gem "wdm", :group => [:development, :test]
end
#gem 'wdm', '>= 0.1.0'

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin]

Solution

  • It is because you disabled the session middleware (look at the output of rake middleware). Omniauth will not work without the session middleware.

    You disabled it here: Rails.application.config.session_store :disabled

    If you are trying to ditch session because you do not use it other than for Omniauth, then the only thing you can do is write your own middleware that injects ActionDispatch::Session::CookieStore and possibly other necessary middlewares based on the URL (i.e. if the URL is /auth/*). Here is an example of what I use to achieve this (only uses session if URL path is not /api/...):

    # /config/application.rb
    config.middleware.insert_before ActionDispatch::ParamsParser, "SelectiveStack"
    
    # /config/initializers/omniauth.rb
    ::OmniAuthConfig = Proc.new do
      provider :github, # ...
    end
    
    # /app/middleware/selective_stack.rb
    class SelectiveStack
      def initialize(app)
        @app = app
      end
    
      def call(env)
        if env["PATH_INFO"].start_with?("/api/") # <--- Change URL path here
          @app.call(env)
        else
          middleware_stack.build(@app).call(env)
        end
      end
    
    private
      def middleware_stack
        @middleware_stack ||= begin
          ActionDispatch::MiddlewareStack.new.tap do |middleware|
            # needed for OmniAuth
            middleware.use ActionDispatch::Cookies
            middleware.use Rails.application.config.session_store, Rails.application.config.session_options
            middleware.use OmniAuth::Builder, &OmniAuthConfig
            # needed for Doorkeeper /oauth views
            middleware.use ActionDispatch::Flash
          end
        end
      end
    end
    

    In this example I only enable the session middleware when the URL does not start with /api/. You will still need to remove Rails.application.config.session_store :disabled and properly set up your session store, of course. In my example I use the cookie store. You might need to tweak my example based on which middleware you are missing in rake middleware. But if you're not doing this for performance reasons then just reenable the session middleware.