I have an rails app that only logged users can access all the application functions. It's not possible to create or remove users, only the admin can create/delete new users from command line or seed files. Ruby version is 2.5.3 and Rails is 5.2.2 with devise to authentication. From 4 days now I've been running into this issue in development:
Started GET "/manifest.json" for ::1 at 2020-08-16 18:53:26 -0300
Started GET "/serviceworker.js" for ::1 at 2020-08-16 18:53:28 -0300
Started POST "/users/sign_in" for ::1 at 2020-08-16 18:53:29 -0300
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"****", "user"=>{"email"=>"****@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Submit"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
Everything was working fine before this and it started to happen without any changes in my code. This seems to happen only in development environment on google chrome. I've ran rails server and tested in others browsers like Opera and Firefox and the development environment still works fine in these browsers.
Some fixes that I've tried to do:
Turn off and on cookies, clear all browser data and restart pc several times, reinstall the browser, remove all turbolinks, add rack-cors gem and some code changes like below.
Change protect_from_forgery with: :exception to protect_from_forgery prepend: true, with: :exception in my application_controller.rb.
Check if <%= csrf_meta_tags %> was present in my view. It was.
Add skip_before_action :verify_authenticity_token to application_controller.rb.
When I add skip_before_action :verify_authenticity_token it seems to solve the error, but the user still cannot log in. Example below:
Started GET "/manifest.json" for ::1 at 2020-08-16 19:12:58 -0300
Started GET "/serviceworker.js" for ::1 at 2020-08-16 19:12:59 -0300
Started POST "/users/sign_in" for ::1 at 2020-08-16 19:13:05 -0300
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"****", "user"=>{"email"=>"****@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Submit"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["email", "****@gmail.com"], ["LIMIT", 1]]
↳ /home/******/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Redirected to http://localhost:3000/
Completed 302 Found in 135ms (ActiveRecord: 0.8ms)
Started GET "/" for ::1 at 2020-08-16 19:13:05 -0300
Processing by PassthroughController#index as HTML
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
My application_controller.rb is:
class ApplicationController < ActionController::Base
protect_from_forgery prepend: true, with: :exception
before_action :authenticate_user!
end
My User.rb file:
class User < ApplicationRecord
devise :database_authenticatable, :rememberable, :validatable
end
My passthrough_controller.rb
class PassthroughController < ApplicationController
def index
path = case current_user.port
when '****'
****_map_path
when '***'
***_map_path
else
new_user_session_path
end
redirect_to path
end
end
My routes.rb:
Rails.application.routes.draw do
devise_for :users
devise_scope :user do
authenticated :user do
get '****/map', to: '****#map'
get '****/report', to: '****#report'
get '***/map', to:'***#map'
get '***/report', to:'***#report'
end
unauthenticated do
root to: 'passthrough#index', as: :unauthenticated_root
get '****/map', to: 'passthrough#index'
get '****/report', to: 'passthrough#index'
get '***/map', to: 'passthrough#index'
get '***/report', to: 'passthrough#index'
end
end
end
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
root GET / passthrough#index
****_map GET /****/map(.:format) ****#map
****_report GET /****/report(.:format) ****#report
***_map GET /***/map(.:format) ***#map
***_report GET /***/report(.:format) ***#report
unauthenticated_root GET / passthrough#index
GET /****/map(.:format) passthrough#index
GET /****/report(.:format) passthrough#index
GET /***/map(.:format) passthrough#index
GET /***/report(.:format) passthrough#index
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
This is my new user session form:
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name), html: {id: "login-form"} ) do |f| %>
<div class="form-inputs">
<%= f.input :email,
required: false,
autofocus: true,
input_html: { autocomplete: "email" } %>
<%= f.input :password,
label: 'Password',
required: false,
input_html: { autocomplete: "current-password" } %>
<%= f.input :remember_me, label: 'Remember me', as: :boolean if devise_mapping.rememberable? %>
</div>
<div class="form-actions session-btn">
<%= f.button :submit, "Submit" %>
</div>
<% end %>
This is my application.html.erb:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<%= render 'shared/head' %>
<meta property="og:title" content="****" />
<meta property="og:description" content="*****" />
<meta property="og:image" itemprop="image" content="******">
<meta name="apple-mobile-web-app-capable" content="yes" />
<%= favicon_link_tag asset_path('icon.png') %>
<title>****</title>
<%= csrf_meta_tags %>
<%= action_cable_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all' %>
<link rel="manifest" href="/manifest.json" />
</head>
<body>
<% exclude_navbar_from_views = ['sessions', 'passwords', 'registrations'] %>
<% if exclude_navbar_from_views.include?(controller_name) %>
<%= yield %>
<% else %>
<%= render 'shared/navbar' %>
<%= render 'shared/flashes' %>
<%= yield %>
<% end %>
<%= javascript_include_tag 'application' %>
<%= javascript_pack_tag 'application' %>
</body>
</html>