Using the JWT gem on rails
Using the JWT gem rails authorization, allows the user to login into their own account and keep them logged in without having to log back in every time they refresh or load a new page.
Using a React frontend and a rails backend.
create a new Rails backend API
rails new <backend_project_name> --api -T --database=postgresql
add the following gems to the Gemfile
gem 'bcrypt', '~> 3.1.7'
gem 'active_model_serializers'
gem 'jwt'
gem 'rack-cors'
create a new React frontend
npm install -g create-react-app
create-react-app <frontend_project_name>
npm install react-router-dom
Setup the backend
Create the models, controllers, serializer
rails g resource User username password_digest name age:integer
Enable the CORS in your app by uncomment the following in config/initializers/cors.rb
In the config/initializers folder, create a new file call active_model_serializers.rb. Then add the following into the file.
ActiveModelSerializers.config.default_includes = '**'
The Serializer gem will help get all the data associated with that model. For example
The attributes will display what type of data to render. The has_many associate the models.
This example user — < outfit — < appointment. When fetching the JSON data. Outfits will be a key inside the user. Appointments will be a key inside the outfits. Without the serializer 3 different fetch request is needed.
The BCrypt gem allows us to salt users’ plaintext passwords. The password_digest
in the Migrate table as well as has_secure_password
in the Model comes from this gem. Add the has_secure_password to the User model.
Token-based authentication is stateless. The client (browser) stores a token and sends that token along with every authenticated request. We can encode user data with JSON Web Tokens (JWT) and store that encoded token onto client-side.
JWT.encode
takes up to three arguments: a payload to encode, a secret, and (optionally) a hashing algorithm. This method returns a JWT as a string.JWT.decode
takes up to three arguments: a JWT as a string, a secret, and (optionally) a hashing algorithm.- The payload is the data that we want to encode.
Setting Up the Routes and Controllers
Add the followings routes
In the Application Controller
Add the encode_token method. Will return as a encrypted string.
Add the decoded_token method. Will return the hash data.
The logged_in_user method. The user_id will be a number and we want to find the user with that number.
The authorized method checks to see if there is a user logged in.
In the User controller
Add the before_action :authorized.
Also add a before_action :authorized, only: [:method] in other controllers that requires the user to be logged in. Ex: [:create, :destroy]
If true, the backend render out the user and token data to the frontend. The token will be the user_id.
In the keep_logged_in method, after checking if the user exist from the application controller. It will render out the user and token data to the frontend.
The FrontEnd
In the App.js. Set the initial state to be empty.
In the login component, in the form, create a POST request entering the username and password. If true, we will get back a user and a token data from the backend.
Upstream the received data back to the App.js,
The user and the token key is what we want to have in our state. Once the token is received in the frontend, the localStorage (the browser) will also have a key call token.
Checking if localStorage.token exist, if true, it will keep requesting as long as the user is still logged in.
To log out. We want to reset our state and clear out the localStorage to remove the token.
GET, POST, PATCH, DELETE REQUESTS
Add to the headers “authorization” : this.props.token
LoGgiNg OuT . . .
Checkout my My Mod4 Project. Link below.