Create your first Go REST API with JWT Authentication in Gin Framework
What is JSON Web Token?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
Our simple REST API Design
so for this project, we will need to create 2 public endpoints that will be used as authentication and 1 protected endpoint that will be protected by our JWT
Login
this route will be used to authenticate the user by providing a username and password then generate and gives JSON Web Token in return
/api/login
Register
of course, because we have a login route earlier we need a way to register our login information, so it can be verified.
/api/register
for the sake of this tutorial, we will leave the registration route open. If you don't want people to be able to gain login access easily you might not want to do this.
Protected Route
this will be the route for our protected endpoints
/api/admin/user
Getting Started
to initiate our project we want to create our project dir folder and going into the directory
mkdir jwt-gin
cd jwt-gin
we can start by initiating our go.mod file to manage packages that we will be installing later on.
go mod init <your_project_name>
here’s the list of packages that we will need to install for this project.
// gin framework
go get -u github.com/gin-gonic/gin// ORM library
go get -u github.com/jinzhu/gorm// package that we will be used to authenticate and generate our JWT
go get -u github.com/dgrijalva/jwt-go// to help manage our environment variables
go get -u github.com/joho/godotenv// to encrypt our user's password
go get -u golang.org/x/crypto
Alright.. now that everything is set, we can start coding our application!
Creating our first endpoint
we can start by creating our main.go file in our root directory
touch main.go
here is the code for our starter public endpoint
and we can try to run it.
// to run the server
go run main.go
Perfect! it seems our register endpoint is working properly.
Creating Register Endpoint
Now that our register endpoint is ready, we can start creating our controller file that will contain our logic for the registration process.
create controller package dir
mkdir controllers
create controller file for our login that will be named auth.go
touch ./controllers/auth.go
and we also have to update our main.go file
now let's test it again!
Perfect!
Validation
we need to validate inputs that are coming into our register endpoint, the only input we will need are username and password.
we will be using a validation feature that comes with gin which is called binding.
if you want to know more about binding and validator
let's update our auth.go file
let's test our validation!
missing password input test :
correct input test:
Database Connection and Model
To save our credentials in our database, we need to create a database connection to our desired database, I will be using MySQL database that is already installed in my system.
let's create models package
mkdir models
this folder will contain the database connection file and all our models
database connection file
touch ./models/setup.go
Alright as you can notice in the setup.go file we will need 2 things
- .env file
- User model
Creating .env file
we can create the .env file by simply creating it in our root directory
touch .env
Making User Model
touch ./models/user.go
Alright, now that our database connection is set let's add it to our main.go file and test it!
this is what you should see in your terminal
Perfect! now we can save the credential into the database.
let's update our auth.go file
in order to save our User data we need to create the SaveUser() function in our User model but we also need to create gorm hooks BeforeSave() function that will be running the hash process to the user’s password.
let's update our user.go file
Let's test it!
Perfect, It means the credential is saved and hashed and we can use it to validate the login process!
Creating Login Endpoint
what our login endpoint going to do is very simple, it will receive a username and password, check whether it matches the credential in our database, if it does return a token, if it doesn’t return an error response.
let's add a new route to our main.go
add Login function in auth.go controller
the Login controller function will call LoginCheck function from user.go
lets add it to our user.go file
we also need to create token.go file that will contain all of our token processing functions, we will create a new directory which is called utils
mkdir utils
mkdir ./utils/token
touch ./utils/token/token.go
here’s token.go file along with several functions that we will be using later on as well.
we also need to add 2 new variables into our .env file
which is TOKEN_HOUR_LIFESPAN and API_SECRET
API_SECRET=yoursecretstring
TOKEN_HOUR_LIFESPAN=1
TOKEN_HOUR_LIFESPAN will determine how long each token will last (hour)
API_SECRET is your own secret string for signing the token
let's run and test our Login
Perfect!
Creating JWT Authentication Middleware
lets create our middleware.go file
mkdir middlewares
touch ./middlewares/middlewares.go
let's implement to our middleware to our main.go
lets add CurrentUser function in our auth.go file so we can return the current authenticated user data.
lets add GetUserByID function into our user.go
you can also notice we ran PrepareGive function to remove the hashed password string before returning it for security purposes.
let's test our protected endpoint
Perfect!
By that, it will conclude the tutorial. I hope it helps you on your personal journey as a developer.
Thank you, See you later! 😀👋