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

Can't verify CSRF token in production #5298

Open
valentin2105 opened this issue Oct 8, 2020 · 11 comments
Open

Can't verify CSRF token in production #5298

valentin2105 opened this issue Oct 8, 2020 · 11 comments

Comments

@valentin2105
Copy link

valentin2105 commented Oct 8, 2020

Hello,

Environment

  • Ruby 2.7.1p83
  • Rails 6.0.3.3
  • Devise 4.7.3

Current behavior

When I setup my app in production mode (in local or in Docker with Postgres), I cannot create a new user and/or login.
here is the logs :

(Everything work fine in Dev environment. )

I, [2020-10-08T15:14:27.343554 #64223]  INFO -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac] Started POST "/users" for 127.0.0.1 at 2020-10-08 15:14:27 +1100
I, [2020-10-08T15:14:27.344406 #64223]  INFO -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac] Processing by Devise::RegistrationsController#create as HTML
I, [2020-10-08T15:14:27.344478 #64223]  INFO -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac]   Parameters: {"authenticity_token"=>"filtered", "user"=>{"email"=>"123@toto.nc", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Confirmer"}
W, [2020-10-08T15:14:27.345492 #64223]  WARN -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac] Can't verify CSRF token authenticity.
I, [2020-10-08T15:14:27.345835 #64223]  INFO -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac] Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 952)
F, [2020-10-08T15:14:27.346608 #64223] FATAL -- : [fade9dc3-0be8-4a70-a2b8-78a8bd2420ac]

Expected behavior

Be able to create an account in production environment.

Files :

config/application.rb

require_relative 'boot'
require 'rails/all'

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

module Sauron
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0
    config.application = config_for(:application)
    config.time_zone = 'Pacific/Noumea'

    #config.middleware.insert_after ActionDispatch::Static, Rack::Deflater
    config.i18n.fallbacks = [I18n.default_locale]

    config.hosts << Rails.configuration.application['HOST_DOMAIN']

  end
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
    before_action :authenticate_user!
    protect_from_forgery with: :exception
    before_action :configure_permitted_parameters, if: :devise_controller?

    def get_vm(vmid)
   ...

vars :

APP_SESSION_KEY=""
SECRET_KEY_BASE="03b41cea8586bb5280615a36bf71a5276ac7e05d13200ba0e54d846766f9b14b74419664528180d2d8795c52cf6f6bce40ba86c5c83ae1d11a7cdf3083FILTERED"
DB_PASSWORD=filtered
DB_USER=filtered
DB_HOST=localhost
RAILS_ENV=production
DB_NAME=filtered

Thank you !

@carlosantoniodasilva
Copy link
Member

carlosantoniodasilva commented Oct 8, 2020

Hi @valentin2105, thanks for your submission. Are you able to submit other forms? If so, can you provide a sample app that shows the issue with just Rails & Devise?

We've had similar reports of CSRF / AuthenticityToken errors in the past (feel free to search around the issues tracker, it might help) and it always ends up being something else with the environment, another gem interfering, or Rails itself, but never Devise, as it does nothing "special" regarding CSRF that'd cause invalidation/errors.

@valentin2105
Copy link
Author

valentin2105 commented Oct 8, 2020

Hi @carlosantoniodasilva , I can't try other form because of they are all behind the login form.
Thanks for taking time to take a look,

Here his the mostly empty project,
https://github.com/valentin2105/rails-prod-bug

you can clone it and then,

mv config/application.yml.example config/application.yml
bundle
yarn install --check-files
bundle exec rails db:migrate
bundle exec rails s -p 3000 

Then you can test login in development, that should work with sqlite.

To try in production (you need a PG DB) :

export DB_PASSWORD=PassW0rd
export DB_USER=app
export DB_HOST=localhost
export DB_NAME=apptest 
export SECRET_KEY_BASE=03b41cea8586bb5280615a36bf71a5276ac7e05d13200ba0e54d846766f9b14b74419664528180d2d8795c52cf6f6bce40ba86c5c83ae1d11a7cdf3083a10799
export RAILS_ENV=production
bundle exec rails db:migrate
bundle exec rails s -p 3000 

In production you shouldn't be able to create an account, logs are available at logs/production.log

@mRudzki
Copy link

mRudzki commented Nov 2, 2020

Hi,
@valentin2105 did you manage to overcome your problem?
I have a similar problem which happened during upgrade rails from 6.0.1 to 6.0.3.4.
InvalidAuthenticityToken error is happening also on development environment while I use ngrok to simulate real calls.

@valentin2105
Copy link
Author

Hi @mRudzki ,

I didn't find any solution on this.
@carlosantoniodasilva can you take a quick look in this ?

Thanks a lot !

@eloyesp
Copy link
Contributor

eloyesp commented Jan 28, 2021

I'm having a similar issue with this, and it seems related to the per_form_csrf_tokens option added as default on rails 5. When this option is enabled, the authenticity_token embedded on the form differs to the one added on the layout by default, as the last one is globally valid, while the per-form is only valid there.

It seems that it is quite common to skip the line <%= csrf_meta_tags %> so many applications fallback to the form hidden input.

But it seems that this per-form-token is more fragile and it fails when signing_in on some escenarios (it happens to some users, while most users log-in without any issues). I couldn't reproduce the bug myself.

@carlosantoniodasilva
Copy link
Member

Is this something that only happens with Devise? I am having a hard time thinking how it could be Devise specific to be honest, but I haven't been able to circle back on this and try to investigate more thoroughly. (and if I'm being honest, I have a list of Devise issues to work through before I can get back to this one, but I wanted to leave a note here with that thought.)

@eloyesp
Copy link
Contributor

eloyesp commented Jan 28, 2021 via email

@nCubed
Copy link

nCubed commented Oct 8, 2021

@valentin2105 did you ever resolve your csrf issue?

Not sure if this helps, but the devise readme docs state:

For Rails 5, note that protect_from_forgery is no longer prepended to the before_action chain, so if you have set authenticate_user before protect_from_forgery, your request will result in "Can't verify CSRF token authenticity." To resolve this, either change the order in which you call them, or use protect_from_forgery prepend: true.

From your example code, it looks like you may need to change the order of authenticate_user and protect_from_forgery.

@MARKOTHEDEV
Copy link

What solved it for me was to add the following to settings.py, replacing "<my_domain>" part of course.

CSRF_TRUSTED_ORIGINS = ['https://<my_domain>.com']

@chbach
Copy link

chbach commented Oct 23, 2023

I had a similar issue. It was connected to malformed cookies for rack 3 type applications. I had to upgrade puma to the latest version.

@viktorianer
Copy link

Check a frequent misstep involves misconfiguring CSRF protection when integrating Devise. Previously, protect_from_forgery was automatically prepended to the before_action chain, ensuring CSRF tokens were verified before any controller action. However, this is no longer the default behavior, see https://github.com/heartcombo/devise?tab=readme-ov-file#controller-filters-and-helpers.

Ensure protect_from_forgery is correctly configured to precede any authentication filters, specifically authenticate_user!. By using the prepend: true option, you can ensure that every request is authenticated and verified for CSRF tokens in the correct sequence, maintaining the security integrity of your application.

So, change

protect_from_forgery with: :exception

to

protect_from_forgery with: :exception, prepend: true

Possible duplicates:
#2734
#5652

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

No branches or pull requests

8 participants