Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sidekiq 6.2.0 raises Sidekiq::Web needs a valid Rack session for CSRF protection in a rails app #4850

Closed
johannesengl opened this issue Mar 24, 2021 · 9 comments

Comments

@johannesengl
Copy link

johannesengl commented Mar 24, 2021

Upgrading sidekiq: 6.1.3 → 6.2.0 (minor) #4804 causes Sidekiq::Web needs a valid Rack session for CSRF protection. in a rails app even though we are mounting sidekiq inside the routes like so:

Rails.application.routes.draw do
mount Sidekiq::Web => "/sidekiq"
....
end 

Ruby version: '2.7.2'
Rails version: 6.1
Sidekiq / Pro / Enterprise version(s): 6.2.0

Initializer:

require 'sidekiq'
require 'sidekiq/scheduler'
require 'sidekiq/web'
require 'sidekiq-scheduler/web'
require 'sidekiq/enqueuer'

Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
  [user, password] == [...]
end

if Rails.env.production?
  Sidekiq.configure_server do |config|
    config.redis = { ... }
  end

  Sidekiq.configure_client do |config|
    ......
  end
end

if ENV.fetch('RUN_SIDEKIQ_CRON').to_bool && Sidekiq.server?
  Sidekiq.configure_server do |config|
    config.on(:startup) do
      scheduler_file_content = File.read(Rails.root.join('config/sidekiq_scheduler.yml.erb'))

      Sidekiq.schedule = YAML.safe_load(
        ERB.new(scheduler_file_content).result
      )

      Sidekiq::Scheduler.reload_schedule!
    end
  end
else
  Sidekiq::Scheduler.enabled = false
end

Error:

RuntimeError - Sidekiq::Web needs a valid Rack session for CSRF protection. If this is a Rails app,
make sure you mount Sidekiq::Web *inside* your application routes:
Rails.application.routes.draw do
  mount Sidekiq::Web => "/sidekiq"
  ....
end
If this is a bare Rack app, use a session middleware before Sidekiq::Web:
# first, use IRB to create a shared secret key for sessions and commit it
require 'securerandom'; File.open(".session.key", "w") {|f| f.write(SecureRandom.hex(32)) }
# now use the secret with a session cookie middleware
use Rack::Session::Cookie, secret: File.read(".session.key"), same_site: true, max_age: 86400
run Sidekiq::Web:
@johannesengl johannesengl changed the title Upgrading sidekiq: 6.1.3 → 6.2.0 causes Sidekiq::Web needs a valid Rack session for CSRF protection. in a rails app even though mounting sidekiq inside the routes Upgrading sidekiq: 6.1.3 → 6.2.0 causes Sidekiq::Web needs a valid Rack session for CSRF protection in a rails app even though mounting sidekiq inside the routes Mar 24, 2021
@mperham mperham changed the title Upgrading sidekiq: 6.1.3 → 6.2.0 causes Sidekiq::Web needs a valid Rack session for CSRF protection in a rails app even though mounting sidekiq inside the routes Sidekiq 6.2.0 raises Sidekiq::Web needs a valid Rack session for CSRF protection in a rails app Mar 24, 2021
@mperham
Copy link
Collaborator

mperham commented Mar 24, 2021

It's not clear what the immediate cause is.

Remove scheduler and enqueuer (any 3rd party Sidekiq extensions) and see if it works then.

@mperham
Copy link
Collaborator

mperham commented Mar 24, 2021

Oh, I believe the issue might be Rails API mode. You need to explicitly enable sessions in an API app if you want to mount a Rack app which depends on sessions:

https://edgeguides.rubyonrails.org/api_app.html#using-session-middlewares

@jpaas
Copy link

jpaas commented Mar 26, 2021

We have an api_only config for Rails too and are hitting this error.

@mperham
Copy link
Collaborator

mperham commented Mar 26, 2021

Added a sentence and link to the wiki: https://github.com/mperham/sidekiq/wiki/Monitoring#rails

@mperham mperham closed this as completed Mar 26, 2021
@gagalago
Copy link

as also a bit explained in the wiki, you can also add session middleware only for sidekiq ui

require 'sidekiq/web'

# Configure Sidekiq-specific session middleware
Sidekiq::Web.use ActionDispatch::Cookies
Sidekiq::Web.use ActionDispatch::Session::CookieStore, key: "_interslice_session"

Myapp::Application.routes.draw do
  mount Sidekiq::Web => "/sidekiq"
  # ...
end

@ArielAleksandrus
Copy link

as also a bit explained in the wiki, you can also add session middleware only for sidekiq ui

require 'sidekiq/web'

# Configure Sidekiq-specific session middleware
Sidekiq::Web.use ActionDispatch::Cookies
Sidekiq::Web.use ActionDispatch::Session::CookieStore, key: "_interslice_session"

Myapp::Application.routes.draw do
  mount Sidekiq::Web => "/sidekiq"
  # ...
end

THAT solves the problem!

@blackerhand
Copy link

blackerhand commented Jul 7, 2021

# automatic connection switching
config.active_record.database_selector         = { delay: 2.seconds }
config.active_record.database_resolver         = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session

when I use this code, application.rb I have a problem undefined method `[]=' for nil:NilClass

actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:235:in load!' actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:230:in load_for_write!'
actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:216:in merge!' actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:19:in create'
actionpack (6.1.3.2) lib/action_dispatch/middleware/session/abstract_store.rb:71:in prepare_session' rack (2.2.3) lib/rack/session/abstract/id.rb:265:in context'
rack (2.2.3) lib/rack/session/abstract/id.rb:260:in call' newrelic_rpm (7.1.0) lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in call'
actionpack (6.1.3.2) lib/action_dispatch/middleware/cookies.rb:689:in call' newrelic_rpm (7.1.0) lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in call'

@Nechitadi
Copy link

Nechitadi commented Jan 18, 2022

# automatic connection switching
config.active_record.database_selector         = { delay: 2.seconds }
config.active_record.database_resolver         = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session

when I use this code, application.rb I have a problem undefined method `[]=' for nil:NilClass

actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:235:in load!' actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:230:in load_for_write!' actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:216:in merge!' actionpack (6.1.3.2) lib/action_dispatch/request/session.rb:19:in create' actionpack (6.1.3.2) lib/action_dispatch/middleware/session/abstract_store.rb:71:in prepare_session' rack (2.2.3) lib/rack/session/abstract/id.rb:265:in context' rack (2.2.3) lib/rack/session/abstract/id.rb:260:in call' newrelic_rpm (7.1.0) lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in call' actionpack (6.1.3.2) lib/action_dispatch/middleware/cookies.rb:689:in call' newrelic_rpm (7.1.0) lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in call'

Hey @308820773 did you find a solution for this issue?

@Farranco
Copy link

Sidekiq::Web.use Rack::Session::Cookie, secret: 'SuperSecretKey'

Also worked for me on a Sinatra app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants