2

All I a sudden I can no longer login to my app production environment on heroku. Or, if I do get in, as soon as I click a new link I get redirected to the login screen where I start seeing errors if I try and login again.

The logs are as follows (this was in the case of login, redirect back to login and then login again).

My applications layout includes CSRF_meta_tags

!!!
%html
  %head
    %title= full_title(yield(:title))
    = include_gon(:init => true)
    = stylesheet_link_tag "application", media: "all"
    = javascript_include_tag "application"
    = csrf_meta_tags
    = render 'layouts/shim'
    %meta{content: "width=device-width, initial-scale=1.0", name: "viewport"}/
  %body.container-fluid
    #wrapper
      = render 'layouts/navigation'
      = render partial: "shared/flash_messages", flash: flash
      #content
        = yield
        = render 'layouts/footer'
        %br
        - if request.env['HTTP_USER_AGENT'].downcase.match(/android|iphone|ipad/)
        - else 
          = debug(params) if Rails.env.development?
          = debug(@current_user) if Rails.env.development?

and my application controller is protect_from_forgery with exception.

class ApplicationController < ActionController::Base

  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.

  protect_from_forgery with: :exception

  before_action :authenticate_user!

end

and I have devise for user in my routes file.

  devise_for :users, :skip => [:registrations]
    as :user do
      get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
      put 'users/:id' => 'devise/registrations#update', :as => 'user_registration'
    end

log files are here for reference.

Started GET "/users/sign_in" for 58.7.233.232 at 2014-05-16 23:52:48 +0000
Processing by Devise::SessionsController#new as HTML
2014-05-16T23:52:48.995008+00:00 heroku[router]: at=info method=GET path=/assets/application-7d1b02fae40091844b4f616c7ec89e83.js host=slapp.herokuapp.com request_id=8f86c336-0bf2-4419-a07d-0c7ecf79cfb4 fwd="58.7.233.232" dyno=web.2 connect=1ms service=2ms status=304 bytes=249
  Rendered layouts/_shim.html.haml (0.3ms)
  Rendered devise/sessions/new.html.haml within layouts/application (7.9ms)
  Rendered layouts/_navigation.html.haml (1.2ms)
  Rendered shared/_flash_messages.html.haml (0.4ms)
  Rendered layouts/_footer.html.haml (0.4ms)

Completed 200 OK in 18ms (Views: 14.1ms | ActiveRecord: 0.0ms)
2014-05-16T23:52:54.997215+00:00 heroku[router]: at=info method=POST path=/users/sign_in host=slapp.herokuapp.com request_id=6fd107af-4a46-4315-843c-6bbf46827df0 fwd="58.7.233.232" dyno=web.1 connect=7ms service=41ms status=422 bytes=1729

Started POST "/users/sign_in" for 58.7.233.232 at 2014-05-16 23:52:54 +0000
  vendor/bundle/ruby/2.0.0/gems/devise-3.2.4/lib/devise/controllers/helpers.rb:182:in `handle_unverified_request'

Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"o5NFnMmQQGcmNxPhzvFYOF+ThrcO1cY1VdZozvQmtOI=", "user"=>{"email"=>"admin@domain.com", "password"=>"[FILTERED]"}, "commit"=>"Login"}

Completed 422 Unprocessable Entity in 9ms

  vendor/bundle/ruby/2.0.0/gems/activesupport-4.1.0/lib/active_support/callbacks.rb:160:in `block in halting'
  vendor/bundle/ruby/2.0.0/gems/actionpack-4.1.0/lib/action_controller/metal/request_forgery_protection.rb:197:in `verify_authenticity_token'

  vendor/bundle/ruby/2.0.0/gems/activesupport-4.1.0/lib/active_support/callbacks.rb:166:in `call'

Can't verify CSRF token authenticity
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

  vendor/bundle/ruby/2.0.0/gems/actionpack-4.1.0/lib/action_controller/metal/request_forgery_protection.rb:176:in `handle_unverified_request'
  vendor/bundle/ruby/2.0.0/gems/actionpack-4.1.0/lib/action_controller/metal/request_forgery_protection.rb:202:in `handle_unverified_request'

I am currently troubleshooting with suggestions on this similar question but no luck so far. Considering trying the "protect_from_forgery except: :sign_in" but it seems like an unnecessary compromise if I can find out the root cause.

Community
  • 1
  • 1
Jay Killeen
  • 2,832
  • 6
  • 39
  • 66
  • I have viewed the page source of multiple pages during a session in development environment and the authentication token is always the same. In production it is different between these pages, which I guess which is what is triggering the Can't verify CSRF token authenticity. – Jay Killeen May 17 '14 at 00:43
  • I have tested running 1 dyno in heroku vs more than 1. Once I increase to more than 1 dyno I start getting the issue. When the process switches from web 1 to web 2 the authenticity token is recreated for the user then no longer matches which generates the error. No one seems to be able to tell me why... or more likely I do not know how to ask the question properly. – Jay Killeen May 19 '14 at 03:17

1 Answers1

0

I think the csrf token is being generated in one dyno and the next http request is hitting the second dyno, so the csrf token doesn't match. The csrf token needs saving to a database so it can be shared by both dynos. Try writing out $DYNO when the page is served and when the form is processed. This will show you which dyno is processing the csrf token and whether it is the same dyno or a different one.

Ken Whipday
  • 71
  • 1
  • 2
  • That's interesting. I was reading the [Heroku session affinity](https://devcenter.heroku.com/articles/session-affinity) ( $ heroku features:enable http-session-affinity ) . Do you know if enabling that fixes the issue? – MegaTux Oct 14 '16 at 14:32