How to Implement JWT Authentication in Go? - I
What is?JWT authentication
JWT (short for JSON Web Token) authentication is a popular method for securing web applications and APIs. A JWT is a digitally signed token that contains a set of claims or statements about a user, such as their identity or authorization level. When a user logs in to a web application, the server generates a JWT and sends it back to the client, storing it in a cookie or local storage. The client then sends the JWT with each subsequent request to the server, which verifies the token and uses the user data in the token’s claims to authorize the request.
Why use JWT in Go
JWT is a widely used authentication standard supported by many programming languages and frameworks. Using JWT in Go can simplify authentication and provide a secure way to transmit user data between the client and server. Go’s strong typing and support for concurrency make it well-suited for building scalable and secure web applications, and using JWT can be a useful tool in this regard.
Overview of the blog
In this blog, we will explore how to implement JWT authentication in a Go web application. We will start by setting up the project and installing the required packages. Then, we will look at how to generate a JWT token and how to authenticate it. We will also implement a middleware to protect our routes, and look at how to store the JWT in a cookie for added security. By the end of this blog, you should have a good understanding of how to use JWT authentication in your Go web applications.
Installing Go and dependencies
Before we can begin implementing JWT authentication in our Go web application, we first need to make sure that Go is installed on our system. You can download and install the latest version of Go from the official Go website: golang.org/dl . You can follow our guide on how to install and set up Go: https://rekib-ahmed023.hashnode.dev/installing-and-setting-up-go-for-development
Once Go is installed, we can create a new project directory and initialize it as a Go module. We can do this by running the following commands in our terminal:
mkdir go-jwt-authentication
cd go-jwt-authentication
go mod init go-jwt-authentication
This will create a new directory called go-jwt-authentication, and initialize it as a Go module with the module path go-jwt-authentication.
We will also need to install some additional packages to work with JWT in Go. The two main packages we will be using are jwt-go for generating and verifying JWT tokens, and gin for handling HTTP requests and routing. We can install these packages using the go get command:
go get github.com/dgrijalva/jwt-go
go get github.com/gin-gonic/gin
Creating a new project
Now that we have our project directory set up and our dependencies installed, we can start creating our Go web application. We can create a new file called main.go in the root directory of our project, and start by importing the necessary packages:
package main
import (
? ?"fmt"
? ?"net/http"
? ?"github.com/dgrijalva/jwt-go"
? ?"github.com/gin-gonic/gin"
)
Adding required packages
Next, we can define our main function and start configuring our HTTP server using the gin package:
To start the project, run the following command:
go run main.go
We will come back to defining our routes in later sections of the blog. For now, we have successfully set up our Go project and installed the necessary packages to start implementing JWT authentication in our web application.
Project Structure
When building any Go project, it’s important to follow a well-organized directory structure to maintain code readability, scalability, and maintainability. Here’s an example project structure we’ll be following for our JWT authentication implementation:
├── controllers
│?├── authController.go
│?└── userController.go
├── database
│?└── connection.go
├── helpers
│?├── config.go
│?├── cookieHelper.go
领英推荐
│?└── tokenHelper.go
├── middleware
│?└── authMiddleware.go
├── models
│?└── userModel.go
├── routes
│?├── authRouter.go
│?└── userRouter.go
├── serializers
│?└── serializers.go
├── go.mod
├── go.sum
├── main.go
└── Makefile
This project structure organizes the code by functionality, separating the database connection code from the controllers and middleware code. The routes directory contains the routing configuration for the API endpoints, while the models directory contains the data models used in the application. The helpers directory contains utility functions for handling JWT tokens and cookies, while the serializers directory contains functions for serializing and deserializing data between the application and the client.
Creating User Model
In this section, we will create a User model using Go's gorm package. The User model will define the fields that we want to store in our database for each user. We'll be using the gorm.Model struct, which contains the default fields of id, created_at, updated_at, and deleted_at.
Our User model will also include the following fields:
Here’s what the User model implementation might look like:
package models
import (
? ?"gorm.io/gorm"
)
type User struct {
? ?gorm.Model
? ?FirstName string `json:"first_name" validate:"required"`
? ?LastName? string `json:"last_name" validate:"required"`
? ?Email? ? ?string `gorm:"unique" json:"email" validate:"required,email"`
? ?Password? string `json:"password" validate:"required"`
}
In this implementation, we’ve defined the fields using struct tags, which are used to add metadata to the struct fields. We’ve added the json tag to specify the JSON key for each field, and the validate tag to add validation rules for each field. We've also added the gorm tag to specify the database constraints for the Email field.
By defining our model using struct tags, we can easily serialize and deserialize our model to and from JSON, and we can also easily validate the incoming data before storing it in our database.
Connecting to the Database
Once we have our project structure set up and our user model ready, we can connect to our database using Go’s gorm package. We will create a connection.go file in the database directory, which will handle the database connection and provide a DB object that we can use throughout the application.
Here, we will be using Docker to run our Postgres container. First, make sure that Docker is installed on your system. You can download and install Docker from the official Docker website: docker.com/get-started .
Once Docker is installed, we can create a new container for our Postgres database using the following command:
docker run --name postgres15 -p 5433:5432 -e POSTGRES_USER=myuser -e POSTGRES_PASSWORD=mypassword -d postgres:15-alpine
To simplify the setup process, we can create a Makefile that includes the necessary commands to run the PostgreSQL container and create a new database. This way, we can quickly and easily set up our database without having to manually execute each command.
Here is an example of what the Makefile might look like:
ENV := $(PWD)/.env
include $(ENV)
postgresinit:
? ?docker run --name postgres15 -p $(DB_PORT):5432 -e POSTGRES_USER=$(DB_USER) -e POSTGRES_PASSWORD=$(DB_PASSWORD) -d postgres:15-alpine
postgres:
? ?docker exec -it postgres15 psql
createdb:
? ?docker exec -it postgres15 createdb --username=$(DB_USER) --owner=$(DB_USER) $(DB_NAME)
dropdb:
? ?docker exec -it postgres15 dropdb $(DB_NAME)
.PHONY: postgresinit postgres createdb dropdb
Next, we can create a connection.go file in the database directory with the following code:
Continue here