Search code examples
ruby-on-railssessioncookiessession-cookiessetcookie

The session ID is not given only in the local environment when a user tries to log in


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.

  • Install Git.
  • Pushed my “app1” to GitHub through Git.
  • Install SourseTree, and connected with my GitHub.
  • Clone my “app1” from GitHub through SourceTree, and named it “app2”.

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.

Code

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).

Log

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)

Display of Burp Suite

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. enter image description here

When I try login from the local environment. Both the “Cookie” and “Set-Cookie” cannot be seen. enter image description here

What I have tried

Reboot for the server and my computer did not solve the problem. Several browsers (Google Chrome, Firefox, and Brave) showed the same result.

Versions

ruby 2.6.4p104 RubyGems 3.0.3 Rails 5.2.3 Burp Suite Community Edition 2021.8.2

Postscript

These works did not change the situation.

  • Put bundle exec rake tmp:cache:clear on a command.
  • Put rails tmp:clear on a command.
  • Delete the session history in users_controller.rb
def login_form
  reset_session
  session[:user_id] = nil
  session.delete(:user_id)
end

Solution

  • 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.