JWT Authentication in Go with Gin and Middleware


In this article, I want to walk you through implementing JWT authentication in Go using the Gin framework. JWT (JSON Web Token) is a popular way to handle authentication in web applications, and using middleware in Gin makes it easy to secure your routes.
1. Setting Up Your Go Project
First, initialize a new Go project and install the necessary dependencies:
go mod init jwt-auth-example
go get github.com/gin-gonic/gin
go get github.com/golang-jwt/jwt/v5
2. Creating the JWT Token
JWT consists of three parts: header, payload, and signature. We’ll create a function to generate a token.
package main
import (
"time"
"github.com/golang-jwt/jwt/v5"
)
var jwtSecret = []byte("your_secret_key")
func GenerateToken(username string) (string, error) {
// Create claims with expiration
claims := jwt.MapClaims{
"username": username,
"exp": time.Now().Add(time.Hour * 24).Unix(), // Expires in 24 hours
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtSecret)
}
3. Creating Middleware to Validate JWT
Middleware helps us protect routes by verifying tokens.
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token required"})
c.Abort()
return
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if err != nil || !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
c.Next()
}
}
4. Setting Up Routes in Gin
Now, let’s create routes for login and a protected endpoint.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.POST("/login", func(c *gin.Context) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
}
c.BindJSON(&req)
if req.Username == "admin" && req.Password == "password" {
token, _ := GenerateToken(req.Username)
c.JSON(http.StatusOK, gin.H{"token": token})
return
}
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})
})
r.GET("/protected", AuthMiddleware(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Access granted!"})
})
r.Run(":8080")
}
5. Testing with Postman
Now that our authentication system is ready, let’s test it using Postman.
Step 1: Login to Get a JWT Token
Open Postman and create a POST request to:
http://localhost:8080/login
In the Body tab, select raw and set the type to JSON.
Enter the following JSON payload:
{ "username": "admin", "password": "password" }
Click Send and you should receive a response containing a JWT token:
{ "token": "your_generated_jwt_token" }
Step 2: Access the Protected Route
Copy the JWT token from the login response.
Create a GET request to:
http://localhost:8080/protected
Go to the Headers tab and add a new key-value pair:
Key:
Authorization
Value:
your_generated_jwt_token
Click Send and you should get a response like:
{ "message": "Access granted!" }
If you send the request without a token or with an invalid token, you should get an Unauthorized error.
Conclusion
I hope this guide helped you understand how to implement JWT authentication in Go using Gin and middleware. This setup can be expanded for more complex authentication workflows like user roles and token refresh mechanisms. If you're building secure APIs in Go, JWT is a solid choice!
Subscribe to my newsletter
Read articles from Saad Khaleeq directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Saad Khaleeq
Saad Khaleeq
Creative. Fast Learner. Super Passionate. Highly Enthusiastic.