Sign in and Authentication in Rails
Published: 2023-02-21 19:23:42

# Authentiication

There are a few steps that need to be followed in order for Authentication to work in a web application. The code below will set up some basic sign up and sign in.  Hopefully this step by step can help you quickly get your authentication working.

In your application controller, you need to define your
current user and your authorized user for use in authentication.

 
```
class ApplicationController < ActionController::API
  include ActionController::Cookies
    
        before_action :authorized_user

        def current_user
            @user ||= User.find_by(id: session[:user_id]) if session[:user_id]
        end

        def authorized_user
            render json: {errors: "unauthorized"}, status: :unauthorized unless current_user
        end

        

end
```

In Your Sessions controller is where you define your login route which is a "POST" and your logout which is a "DELETE".
It will create a session and it will delete the session for the user so that the user can see the appropriate information that they are supposed to see rendered to the page. 

```
class SessionsController < ApplicationController
    skip_before_action :authorized_user, only:[:login]
    
    def login
        user = User.find_by(email: params[:email])
        if user&.authenticate(params[:password])
            session[:user_id] = user.id
            render json: user, status: :created            
        else
            render json: {error: "Invalid Credentials"}, status: :unauthorized
        end
    end

    def logout
        session.delete :user_id
        head :no_content
    end
end
```

In your Users Controller or wherever your user is living.  The table will hold all of the users information with a secure password.  login and logout will create a new session where as sign up will allow a returning user sign in on future updates.

```
class UsersController < ApplicationController
    before_action :find_user, only: [ :update, :destroy]
    skip_before_action :authorized_user, only: [:create]

    def create
        new_user = User.create!(user_params)
        session[:user_id] = new_user.id
        render json: new_user, status: :created
    end

    private

    def find_user
        @user = User.find(params[:id])
    end

    def user_params
        params.permit(:email, :password)
    end
end

```
In your User Model is where you will add you validations and have has_secure_password so that creation of your users goes smoothly.

```
class User < ApplicationRecord
 has_secure_password

 validates_presence_of :email
    validates :email, presence: true, uniqueness: true
    validates :password, presence: true, length: { minimum: 8 }, on: :create

end
```

The Authorization Fetch Call in your App.js will make sure that the current user or the one person who is logged in has access to what they need access to and that no one else has access to that information.

```
useEffect(() => {
    const fetchData = () =>
    fetch('/auth')
    .then(res => {
      if(res.ok){
        res.json().then(user => setCurrentUser(user))
      } 
      // else {
      //   const error = res.json().then(error = setError(error))
      // }
    })
    if (!currentUser)
    {fetchData() } 
  },[currentUser])
```

In the routes.rb  custom routes for authorization login and logout.  The custom routes allow for easy identification in naming and calling routes in your front end to make sure they end up correctly in the backend.

```
  post "/login", to: "sessions#login"
  post "/signup", to: "users#create"
  get "/auth", to: "users#show"
  delete "/logout", to: "sessions#logout"
```
In app file

```
if(!currentUser) {
    return login ? <LogIn setLogin={setLogin} setCurrentUser={setCurrentUser} /> : <SignUp setLogin={setLogin} setCurrentUser={setCurrentUser} /> 
  }
```
## In Conclusion
Creation of authentication actually has a lot of moving parts and depending on when you decide on implementing your you make break a lot of things in your site.  Go slowly track your changes.