Rails React Redux Thunk User Auth with Cookies and Sessions — Part I

Luciana
4 min readDec 10, 2021
Uh-oh! Forgot your password?

On my last project as a part-time student at Flatiron School, I created an application to early stage companies that needs help beyond capital. It was meant to be for the 1 Million Cups, a free national meet that happens every Wednesday over 160 communities to give entrepreneurs support, encouragement, and feedback.

The problem: Current, after the Wednesday pitch, there’s no easy way to people around the country/world know about their project, what help it’s needed, or reach out to them.

The solution: A platform with the project information, image, video of their presentation, what they need, and a contribution section. Similar to Kickstarter but focus on early stage projects that not necessarily need funds to bring their project to life.

One feature that I implemented was user authorization using cookies and sessions. I followed the edutechional video playlist to help me implement it on my project but he doesn’t use Redux/Thunk. On this post, I’ll show how I modified these parts to meet the project requirements. First part, implementing the Rails backend and the second part is React Redux Thunk frontend.

To start creating your Rails backend it’s important to don’t use the API flag but the application it’s still be treated as API only.

rails new your-project-name  —database=postgresql

Add ‘bcrypt’ and ‘rack-cors’ inside the Gemfile.

gem 'bcrypt', '~> 3.1.7'
gem 'rack-cors', :require => 'rack/cors'

Run bundle to install them.

Inside Config > Initializers folder create 2 files:

cors.rb
session_store.rb

Inside Config > Initializers > cors.rb

After you deploy your project, change the origins to the deployment url.

Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "http://localhost:3000"
# origins "*"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end

Inside Config > Initializers > session_store.rb

if Rails.env == "production"
Rails.application.config.session_store :cookie_store, key: "_authentication_app", domain: "herokudomain.com"
else
Rails.application.config.session_store :cookie_store, key: "_authentication_app"
end

Inside Config > routes.rb

Rails.application.routes.draw do
resources :sessions, only: [:create]
delete :logout, to: "sessions#logout"
get :logged_in, to: "sessions#logged_in"
root to: "static#home"
end

Inside App > Controllers > static_controller.rb

Create a file called static_controller.rb file

class StaticController < ApplicationController

def home
render json: { status: "It's working"}
end
end

Run rails s on the terminal. It should show on the browser page {“status”: “It’s working”} which means everything is connected! Now it’s time to create the User database, on this example there’s just email and password_digest but you can add more if want to.

On your terminal run rails g model User email password_digest then rails db:createand rails db:migrate

Inside App > Model > user.rb

class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
end

To test if everything is working, run on your terminal rails cand create some fake users

User.create!(email:"test@test.com", password: "123", password_confirmation: "123)User.create!(email:z@dev.com", password: asdfasdf, password_confirmation: asdfasdf”)

Add resources: sessions, only[:create] inside Config > route.rb

Create a sessions_controller.rb inside App > Controllers and add the create user method:

class SessionsController < ApplicationControllerdef create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
render json: {
status: :created,
logged_in: true,
user: user
}
else
render json: { error: user.errors.full_messages }
end
end
def logged_in
if @current_user
render json: {
logged_in: true,
user: @current_user
}
else
render json: {
logged_in: false
}
end
end
def logout
reset_session
render json: { status: 200, logged_out: true }
end
end

Create a user_controller.rb inside App > Controllers and create the index and create methods:

class UsersController < ApplicationController
def index
user = User.all
render json: user
end
def create
user = User.new(user_params)
if user.save
session[:user_id] = user.id
render json: {
status: :create,
logged_in: true,
user: user
}
else
render json: { error: user.errors.full_messages}
end
end
private
def user_params
params.permit(:first_name, :last_name, :email, :password, :about, :image)
end
end

Add skip_before_action :verify_authenticity_tokenand include CurrentUserConcerninside App > Controllers > application_controller.rb

Create a current_user_concern.rb inside App > Controllers > Concerns and add the module current user module:

module CurrentUserConcern
extend ActiveSupport::Concern

included do
before_action :set_current_user
end

def set_current_user
# byebug
if session[:user_id]
@current_user = User.find(session[:user_id])
end
end
end

After these steps, the Rails backend is set up and ready to go! Check the Part II to see the React Redux Thunk frontend set up.

For reference, here are my project Github backend and frontend.

P.S. I also followed the edutechional video playlist steps before I implemented it on my project to make sure it would work. Here are the Github backend and frontend (not using Redux/Thunk).

--

--