Authentication using React and Ruby on Rails: creating a login, staying logged in, and logging out
Published: 2022-12-16 18:03:54

In this post, I will explain how to create a login page using a Ruby on Rails backend and React frontend.

## Add sessions and cookies to application.rb

In config/application.rb, add the following code:

 

```
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore

    # Use SameSite=Strict for all cookies to help protect against CSRF
    config.action_dispatch.cookies_same_site_protection = :strict
```

## Update application_controller.rb

In app/controllers/application.rb, add the following code:

```
include ActionController::Cookies
```

This allows all of our controllers to work with the cookies. After adding the above code, your application_controller.rb should look like this:

```
class ApplicationController < ActionController::API
  include ActionController::Cookies
end
```

## Create a sessions_controller.rb file

One can create a sessions_controller.rb file by entering the following code in the terminal. The command utilizes a rails generator to create a sessions controller. 

```
rails g controller Sessions
```

## Create a login path

In config/routes.rb, add the following route:

```
post "/login", to: "sessions#create"
```

## Create a login request on the frontend

```
function Login(){

    const [username, setUsername] = useState("")
    const [password, setPassword] = useState("")

    
    function handlSubmit(e){
        e.preventDefault()
        const formData = {
            username: username, 
            password: password
        }
        fetch("/login", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify(formData),
          })
            .then((r) => r.json())
            .then(navigate("/"));
        }

     return (
        <div className="login-div">
            <form  className="form" onSubmit={handlSubmit}>
                <input 
                    id="username"
                    type="text"
                    onChange={(e) =>   setUsername(e.target.value)}
                    value={username}
                    placeholder="username"/>
                <input 
                    id="password"
                    type="password"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    placeholder="password"
                />
                <input 
                type="submit"
                value="Login"
                className="login_buttons"
                />
                <h3>OR</h3>
                <button onClick={handleAccount} className="login_buttons">Create Account</button>
            </form>
        </div>
    )
}
```

The above code create a login form and creates a post request for the login path defined in config/routes.rb. These steps will ensure that a person can login using their username and password.


## Remain logged in 

To remain logged in, one must define a route that fetches the data for the user who matches the session id created in the last step. 

In config/routes.rb, define the following route:

```
get "/me", to: "users#show"
```

In your user_controller.rb, create a show method that finds a user with the same session created in the login.

```
class UsersController < ApplicationController
  def show
    user = User.find_by(id: session[:user_id])
    if user
      render json: user
    else
      render json: { error: "Not authorized" }, status: :unauthorized
    end
  end
end
```

Finally, create a get request in React that fetches the data for that specific user.

```
 const [me, setMe] = useState([])
  

  useEffect(() => {
    fetch("/me")
    .then((resp) => resp.json())
    .then((info) => setMe(info))
  },[])
```

## Logging out

In config/routes.rb, create the following route:

```
delete "/logout", to: "sessions#destroy"
```
In sessions controller, define a delete method:

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

In React, create a delete request like the following:

```
function logout(){
  fetch("/logout", {
  method: "DELETE",
  }).then(navigate("/login"));
}
```
## In Conclusion

Creating a login page using ruby and rails and react can be very simple using the above code. One must define the correct routes, define the correct methods in the right controller, and create the correct requests on the frontend.