Even though I did not change any code, the login function does not work, which had been working. Even though I put the correct email address and password, it will be redirected to the login page. I do not use devise.
First, I thought some coding is wrong, but according to the log, it says the email address and password are correct and it tries to redirect to the top page properly.
Next, I used the tool Burp Suite
which tracks the data such as session ID in between the browser and server (local proxy).
And I found out that the session ID is not given after the login, and it brings the error caused by authenticate_user
so that login has been failed.
I want to find out the reason and solve it.
In addition, I used the tool ngrok
which enables users to visit my localhost.
Then surprisingly, the user outside of my local environment was able to log in successfully.
And Burp Suite
showed that the session ID was given property in this case.
Therefore, only when I try to log in from my local environment, the session ID isn’t given. Recently, I did not edit any code but did these tasks below.
Before doing these tasks, I added this code below. But it does not change the situation even though I comment out it.
application.rb
config.session_store :cookie_store, expire_after: 8.hours
All the problems occurred after these tasks.
routes.rb
get "login" => "users#login_form"
post "login" => "users#login"
post "logout" => "users#logout"
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :set_current_user
skip_before_action :verify_authenticity_token
caches_action :set_current_user, :authenticate_user, :forbid_login_user
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
def authenticate_user
if @current_user == nil
flash[:notice] = "You need to log in"
redirect_to("/login")
end
end
def forbid_login_user
if @current_user
flash[:notice] = "You are already logged in"
redirect_to("/")
end
end
end
users_controller.rb
before_action :authenticate_user, {except: [:new, :create, :login_form, :login]}
before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]}
before_action :ensure_correct_user, {only: [:edit, :update]}
before_action :ensure_correct_user_account, {only: [:setting_password, :update_password, :setting_email, :update_email, :delete_account, :destroy]}
caches_action :index, :show, :follow, :new, :create, :edit, :user_params, :update, :destroy, :login_form, :login, :logout, :likes, :ensure_correct_user, :followings, :followers, :top
def login
@user = User.find_by(email: params[:email])
if @user && @user.authenticate(params[:password])
session[:user_id] = @user.id
flash[:notice] = "You have successfully logged in"
redirect_to("/")
else
@error_message = "Email address or password is incorrect"
@email = params[:email]
@password = params[:password]
render("users/login_form")
end
end
def login_form
end
def logout
session[:user_id] = nil
flash[:notice] = "You have successfully logged out"
redirect_to("/login")
end
When a user successfully login, it redirects to “/“ (the top page).
It’s a log when I tried to log in. Seeing Started GET "/"
, the user seems to log in successfully. But then the log says Filter chain halted as :authenticate_user rendered or redirected
, and it redirects to "/login"
.
Started POST "/login" for ::1 at 2021-08-24 14:44:31 +0900
Processing by UsersController#login as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JBcKtTsdCT0JXgyIfzjKVqi/8KEz4pRmUXB2Kybn8eHcnz7UKXoMsbBRkBCnoUqwnIdi4hUkZ/6oQKFVqMyG/g==", "email"=>"hoge", "password"=>"[FILTERED]"}
User Load (35.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
↳ app/controllers/application_controller.rb:9
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'hoge' LIMIT 1
↳ app/controllers/users_controller.rb:255
Redirected to http://localhost:3000/
Completed 302 Found in 422ms (ActiveRecord: 41.9ms)
Started GET "/" for ::1 at 2021-08-24 14:44:32 +0900
Processing by UsersController#top as HTML
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
↳ app/controllers/application_controller.rb:9
Redirected to http://localhost:3000/login
Filter chain halted as :authenticate_user rendered or redirected
Completed 302 Found in 6ms (ActiveRecord: 0.6ms)
Started GET "/login" for ::1 at 2021-08-24 14:44:32 +0900
Processing by UsersController#login_form as HTML
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
↳ app/controllers/application_controller.rb:9
Rendering users/login_form.html.erb within layouts/application
Rendered users/login_form.html.erb within layouts/application (0.9ms)
CACHE User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
↳ app/views/layouts/application.html.erb:51
Completed 200 OK in 244ms (Views: 233.9ms | ActiveRecord: 0.5ms)
How the session ID is given when the user login from outside when I used ngrok
. You can see both the “Cookie” and “Set-Cookie” are displayed.
When I try login from the local environment. Both the “Cookie” and “Set-Cookie” cannot be seen.
Reboot for the server and my computer did not solve the problem. Several browsers (Google Chrome, Firefox, and Brave) showed the same result.
ruby 2.6.4p104 RubyGems 3.0.3 Rails 5.2.3 Burp Suite Community Edition 2021.8.2
These works did not change the situation.
bundle exec rake tmp:cache:clear
on a command.rails tmp:clear
on a command.users_controller.rb
def login_form
reset_session
session[:user_id] = nil
session.delete(:user_id)
end
I was able to solve the problem by myself.
I made the file session_store.rb
in the past, and it was the cause.
config > initializers > session_store.rb
app_name = "app_name"
Rails.application.config.session_store :cookie_store, key: "_app_name_session", expire_after: 8.hours, secure: true
secure: true
disables http to pass the cookie, so I could not log in only on the localhost. I forgot to delete this file.
I deleted session_store.rb
, and wrote the code below in application.rb
.
config.session_store :cookie_store, expire_after: 8.hours, secure: Rails.env.production?
Now, the log in function does work on the localhost too.