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)