I am working on running a Rails application in production. It's still a proof of concept, but I'm running into ActionController::InvalidAuthenticityToken
exceptions for form submissions. My understanding is that in Rails 6 (or maybe earlier?) the protect_from_forgery
callback is now called by default. To get it to work, I added the configuration option config.action_controller.allow_forgery_protection = false
in my config/environments/production.rb
file, and now I'm working on re-enabling forgery protection so I removed the override and attempted to submit some forms (or log out, basically anything that uses a POST/PUT/PATCH/DELETE method).
My ApplicationController does not call protect_from_forgery
manually, and all GET requests appear to be working just fine. My application.html.haml
includes the following within %head
:
= csrf_meta_tags
= csp_meta_tag
My forms are using bootstrap_form_with
and the form is submitting an authenticity_token
form parameter that matches what is in the %head
(verified from Chrome dev tools and the logs). When I submit, I see that the response is a 422 error with the exception in the logs:
[3d603471-3240-4401-a3a2-e9ba3c6ac358] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
[3d603471-3240-4401-a3a2-e9ba3c6ac358]
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/request_forgery_protection.rb:217:in `handle_unverified_request'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/request_forgery_protection.rb:249:in `handle_unverified_request'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] devise (4.7.1) lib/devise/controllers/helpers.rb:255:in `handle_unverified_request'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/request_forgery_protection.rb:244:in `verify_authenticity_token'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:429:in `block in make_lambda'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:201:in `block (2 levels) in halting'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:202:in `block in halting'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `block in invoke_before'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `each'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `invoke_before'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:110:in `block in run_callbacks'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] ahoy_matey (3.0.1) lib/ahoy/controller.rb:45:in `set_ahoy_request_store'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:121:in `block in run_callbacks'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:139:in `run_callbacks'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/abstract_controller/callbacks.rb:41:in `process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/rescue.rb:22:in `process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/instrumentation.rb:33:in `block in process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/notifications.rb:180:in `block in instrument'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/notifications.rb:180:in `instrument'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activerecord (6.0.2.1) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/abstract_controller/base.rb:136:in `process'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionview (6.0.2.1) lib/action_view/rendering.rb:39:in `process'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal.rb:191:in `dispatch'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_controller/metal.rb:252:in `dispatch'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:51:in `dispatch'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:33:in `serve'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/routing/mapper.rb:18:in `block in <class:Constraints>'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/routing/mapper.rb:48:in `serve'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:49:in `block in serve'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:32:in `each'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:32:in `serve'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:837:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] warden (1.2.8) lib/warden/manager.rb:36:in `block in call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] warden (1.2.8) lib/warden/manager.rb:34:in `catch'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] warden (1.2.8) lib/warden/manager.rb:34:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/tempfile_reaper.rb:15:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/etag.rb:25:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/conditional_get.rb:38:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/head.rb:12:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/session/abstract/id.rb:259:in `context'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/session/abstract/id.rb:253:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/cookies.rb:648:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] turbolinks_render (0.9.17) lib/turbolinks_render/middleware.rb:77:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] ahoy_matey (3.0.1) lib/ahoy/engine.rb:22:in `call_with_quiet_ahoy'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] request_store (1.5.0) lib/request_store/middleware.rb:19:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/method_override.rb:22:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/runtime.rb:22:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] rack (2.0.8) lib/rack/sendfile.rb:111:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] puma (4.3.1) lib/puma/configuration.rb:228:in `call'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] puma (4.3.1) lib/puma/server.rb:681:in `handle_request'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] puma (4.3.1) lib/puma/server.rb:472:in `process_client'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] puma (4.3.1) lib/puma/server.rb:328:in `block in run'
[3d603471-3240-4401-a3a2-e9ba3c6ac358] puma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
I saw that devise
recommended that I use prepend on the forgery protection, so I added the following to the ApplicationController:
protect_from_forgery with: :exception, prepend: true
I'm a bit stumped as to why this is happening, and can certainly provide some more code samples, but I'm not entirely sure what is necessary.
Thanks so much
In my case, solving this involved enabling the option in config/environments/production.rb
as shown:
config.force_ssl = true
I'm not sure if this is the only thing, unfortunately, since it was a while since I asked the question, however, after I enabled it request forgery protection started working.