Checklist for HTTP Rails/React user auth setup - Rails backend setup checklist.
Published: 2020-05-06 12:19:15

---
title: Checklist for HTTP Rails/React user auth setup - Rails backend setup checklist.
published: true
description: 
tags: 
---
This article is written as a destilling of [this](https://www.youtube.com/watch?v=z18zLCAg7UU&list=PLgYiyoyNPrv_yNp5Pzsx0A3gQ8-tfg66j&index=1) video series by [Edutechional](https://www.youtube.com/user/edutechional). If this is your first time creating a user authentication with Rails and React I would highly recommend watching the 10 video series to understand what is going on. I also recommend any of other videos he offers, his way of explaining is straightforward and easy to understand. If, however, this isn't your first time setting up a back end cookie based user auth and you just want a nitty gritty checklist of an auth framework, you've come to the right place! I tried to grab every bit of code needed to get it working with minimal descriptions to streamline flow. Good luck.

---
-Create new app in Rails with a pstgresql database and create the database
```Rails
rails new app_name --database=postgresql
rails db:create
```

-Get latest version of [bcrypt](https://rubygems.org/gems/bcrypt) in your gemfile as well as rack-cors. At the time of writing this article:
####Gemfile
```Ruby
gem 'bcrypt', '~> 3.1', '>= 3.1.13'
gem 'rack-cors', :require => 'rack/cors'
```
-update gems with console command of preference, I use
```
bundle
```
---
####create file app/config/intilizers/cors.rb
```Ruby
Rails.application.config.middleware.insert_before 0, Rack::Cors do
    #first origin is your API host address
    allow do
        origins "http://localhost:3000"
        resource "*", headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true
    end
    #second origin is front end host address
    allow do
        origins "http://app_name.herokuapp.com"
        resource "*", headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true
    end
end
```
---
####create file app/config/intilizers/session_store.rb
```Ruby
#key is how you want it to be identified in cookies, domain is same as above in cors file
Rails.application.config.session_store :cookie_store, key: "_appname", domain: "app_name.herokuapp.com"
```
---
####app/config/routes.rb
```Ruby
root to: "static#home"
```
---
####create file app/controllers/static_controller.rb
```Ruby
class StaticController < ApplicationController
    def home
        render json: { status: "It's working"}
    end
end
```
#************
#Check point
#************
You should be able to visit your backend host (My example is http://localhost:3000) and have it show the json string
```JSON
{"status": "It's working"}
```

-Create your user model, it must have a password_digest attribute. I am also adding email for validation. Then migrate models.
```Rails
rails g model User email password_digest
rails db:migrate
```
---
####app/models/user.rb
```Ruby
class User < ApplicationRecord
    has_secure_password
    #sets email as required attribute for model creation
    validates_presence_of :email
    #validates unique emails
    validates_uniqueness_of :email
end
```
##---Quick check---
If you did this correctly then you should be able to create a user in the Rails console and it should store a user model with an encrypted password_digest. User creation should look like this for encryption:
```Rails
User.create(email: "email@address.com", password: "password", password_confirmation: "password")
```
---
####app/config/routes.rb
```Ruby
Rails.application.routes.draw do
  resources :sessions, only: [:create]
  resources :registrations, only: [:create]
  root to: "static#home"
end
```
---
####Create app/controllers/sessions_controller.rb
```Ruby
class SessionsController < ApplicationController
    def create
        user = User.find_by(email: params["user"]["email"]).try(:authenticate, params["user"]["password"])

        if user
            session[:user_id] = user.id
            render json: {
                status: :created,
                logged_in: true,
                user: user
            } 
        else
            render json: { status: 401 }
        end
    end
end
```
---
####Create app/controllers/registrations_controller.rb
```Ruby
class RegistrationsController < ApplicationController
    def create
        user = user.create!(
            email: params['user']['email'],
            password: params['user']['password'],
            password_confirmation: params['user']['password_confirmation'],
        )

        if user
            sessions[:user_id] = user.id 
            render json{
                status: created,
                user: user
            }
        else
            render json: {status: 500}
        end
    end
end
```
---
####app/controllers/application_controller.rb
```Ruby
class ApplicationController < ActionController::Base
    skip_before_action :verify_authenticity_token
end
```
#************
#Check point
#************

To test the current interactions, start the rails server and in another terminal interface do the following (user info should be the same as the user created at previous checkpoint). Use your hosting address.
```CLI
curl --header "Content-Type: application/json" \
--request POST \
--data '{"user": {"email": "z@dev.com", "password": "asdf"}}' \
http://localhost:3000/sessions
```
You should get some message similar to
```CLI
{"status":"created","logged_in":true,"user":{"id":1,"email":"z@dev.com","password_digest":"$2a$12$m9er4Bkndom7g5I85Ppj0Ob8EoPYkcw/gApT1ofEz2Ld3y4Eopbzy","created_at":"2020-04-26T02:15:57.844Z","updated_at":"2020-04-26T02:15:57.844Z"}}
```
---
####app/config/routes.rb
```Ruby
Rails.application.routes.draw do
  resources :sessions, only: [:create]
  resources :registrations, only: [:create]
  resources :logout, to: "sessions#logout"
  get :logged_in, to: "sessions#logged_in"
  root to: "static#home"
end
```
---
####Create app/controllers/concerns/current_user_concern.rb
```Ruby
module CurrentUserConcern 
    extend ActiveSupport::Concern

    included do
        before_action :set_current_user
    end

    def set_current_user
        if sessions[:user_id]
            @current_user = User.find(session[:user_id])
        end
    end
end
```
---
####app/controllers/sessions_controller.rb
```Ruby
class SessionsController < ApplicationController
    include CurrentUserConcern

    def create
        #unchanged
    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
```
---
####app/config/initializers/session_store.rb
```Ruby
if Rails.env == "production"
    Rails.application.config.session_store :cookie_store, key: "_homesteadtogether", domain: "jdh-homesteadtogether.herokuapp.com"
else
    Rails.application.config.session_store :cookie_store, key: "_homesteadtogether",
```
#Finished!
That should complete the backend of the api. I will try to compress this into more concise single page paragraphs in the future. Working on the front end walkthrough now.