top of page

User Authentication in React With Redux

SERVER SIDE

CONFIGURATION

  • Add "bcrypt" to your gemfile

  • Add "jwt" to you gemfile

  • Remember to run bundle install

 

SET UP THE MODEL

  • Add "has_secure_password"

  • Add authenticate class method that takes in email (or username) and password

 

CREATE THE MIGRATION

Add the column for password_digest

TEST

Test if it works in the Rails console.

  • Create a user with password.

  • User.authenticate([email], [password])

  • It should return the User record.

 

ADD THE ROUTES

 

ADD APPLICATION CONTROLLER HELPER METHODS

 

ADD AUTH CONTROLLER

User Postman to test if it works

  • Send POST request to your API endpoint

  • Add user params in the request's body

  • Should return json specified in AuthController

CLIENT SIDE

ADD AUTH ADAPTER

  • Add login method that takes in login parameters (email and password) to send the request to the database

  • Add current user method that finds the current user via the jwt token

 

ADD LOGIN LOGIC

The login method is added to the Login component, which will be triggered once the user submits the login form.

 

SET THE REDUCER AND ACTION

Once the user is found the redux store is updated with the user object (which is being assembled by auth#create). The reducer looks like this:

The corresponding action is pretty straightforward:

 

Don't forget to connect the dispatch method with the component so that it can update the redux store.

ADD THE LOGIN LOGIC TO ROUTES

The routes uses a simple ternar to authenticate users with isLoggedIn. App.isLoggedIn checks if the user has been set in the redux store:

 

SUMMARY OF THE LOGIN PROCESS - INITIAL LOGIN

This process is triggered once when the user types in his email and password and submits the form.

Frontend:

  1. User submit from the Login component invokes AuthAdapter.login with the parameters email and password

  2. AuthAdapter.login assembles the header and sends the request to the API endpoint 'login'

Backend:

  1. The API endpoint hits the method auth#create

  2. auth#create does multiple things:

  • looks for the user with the given arguments (email, password)

  • creates the jwt token (with the helper method application#issue_token

  • returns the user object and the jwt token

Frontend:

onLogin receives the user object

  • sets the localStorage with the jwt

  • sets the redux store with the user object

  • the routes check if the user object is present in the redux store; if no user has been set, the user is redirected to the login/main page

The request to retrieve the current user will hit the endpoint 'me' and the controller method auth#show (see above for ApplicationController).

 

SUMMARY OF THE CURRENT USER PROCESS - AFTER INITIAL LOGIN

This process is triggered every time a page is being refreshed. The user has already been authenticated on intial login and the jwt token is stored in the browser, so there is no need to create a new one. Instead of asking the user to re-submit his login credentials the jwt from localStorage will be sent to the backend. There it is being decoded and the user object is being returned so that the redux store can be refreshed. It is very similar to the login process, except that we are hitting auth#show instead of auth#create

Frontend:

componentWillMount -> AuthAdapter.currentUser sends the jwt token to the API

Backend:

  1. The API endpoint hits the method auth#show

  2. auth#show does multiple things:

  • the helper method Application#authorize! intercepts auth#show if no user is being found

  • auth#show calls Application #current_user

  • Application#currentUser calls various helper methods

  • #token grabs the token from the HTTP request header

  • #decoded_token uses the JWT method to turn the hashed string into the original object

  • #token_user_id returns the user id

  • #current_user uses the user id to query the database and returns the user object

  • auth#show renders the json object with the user info

Frontend:

componentWillMount -> AuthAdapter.currentUser uses the object to set the user in the redux store

  • sets the localStorage with the jwt

  • sets the redux store with the user object

  • the routes check if the user object is present in the redux store; if no user has been set, the user is redirected to the login/main page

You Might Also Like:
bottom of page