I just want to start off by saying, I did not really focus on my User Login, this is just my experience setting it up.
Gems
The gems I used are as followed:
- bcrypt
- dotenv-rails
- jwt
I used the JSON Web Token (JWT) gem in my rails backend, this helped out using authentication in the frontend. Setting this up was very confusing and frustrating. Luckily google is a thing and that helped me out a lot (I will have a link for what really helped me out). A lot of things that I will be saying in this probably wont make sense, I am not the best at explaining stuff.
Models
I started by creating a User model with username and password (password_digest). This was the first thing I did before implementing all my other models, I just wanted to get this out of the way.
class User < ApplicationRecord has_secure_password validates :username, presence: true, uniqueness: true validates :password, presence: true end
Controllers
There are 3 controllers that help with user authentication:
- application_controller (this is where you configure your JWT)
- users_controller
- sessions_controller
application_controller
class ApplicationController < ActionController::API def jwt_key ENV['SESSION_SECRET'] end def issue_token(user) JWT.encode({user_id: user.id}, jwt_key, 'HS256') end def decoded_token begin JWT.decode(token, jwt_key, true, { :algorithm => 'HS256' }) rescue JWT::DecodeError [{error: "Invalid Token"}] end end def token request.headers['Authorization'] end def user_id decoded_token.first['user_id'] end def current_user @user ||= User.find_by(id: user_id) end def logged_in? !!current_user end end
This is where I needed to google. I found examples that used the dotenv gem to hide my sessions secret which was the JWT token. You can get your own JWT token by going to JWT Website, scroll down under Debugger and find something that looks like this:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret (This is what you want) ) secret base64 encoded
rename your-256-bit-secret to whatever you want, make it lengthy. It will tell you if it is okay to use. Paste your secret into your dotenv like this:
SESSION_SECRET = your-256-bit-secret
users_controller
This controller is pretty simple to setup. You just need a create method and a user params. This is my create method. I recommend using it:
def create user = User.new(user_params) if user.save token = issue_token(user) render json: { valid: "true", user: {id: user.id, username: user.username}, token: token} else render json: { valid: "false", errorMessages: user.errors.messages } end end
For the user_params just permit username and password.
sessions_controller
This controller is used to authenticate if your username and password is correct and if the current user is you. It also issues a token from jwt each time a session is created. This has two methods in it, create and show:
def create user = User.find_by(username: params[:username]) if user&.authenticate(params[:password]) token = issue_token(user) render json: { valid: "true", user: {id: user.id, username: user.username}, token: token} else render json: { valid: "false", errorMessages: {login: "username or password is wrong"} } end end def show if logged_in? render json: { valid: "true", user: {id: current_user.id, username: current_user.username} } else render json: { valid: "false", errorMessages: {session: "Please login to continue"}} end end
Routes
post '/login', to: 'sessions#create' get '/authorize', to: 'sessions#show'
When the user logs in it will make a new session and it will authorize to see if you are logged in.
Thats the rest for the backend. Sorry if I didn't explain it that well but most of this stuff I found googling.
Conclusion
When I setup my frontend to have a user login function, it was a pretty easy for me from that point on. I know I didn't explain everything fully in-depth but I hope this helped. I personally don't know if this is the proper way. Make sure to check out the link below for more information regarding JWT setup.
Resources
JWT Setup - Kailana Kahawaii explains it more in depth. This is what really helped me out setting this up, so if you want a more in-depth tutorial, check this blog out.
Top comments (0)