JWT Authentication in Go with Gin and Middleware

Saad KhaleeqSaad Khaleeq
3 min read

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

  1. Open Postman and create a POST request to:

     http://localhost:8080/login
    
  2. In the Body tab, select raw and set the type to JSON.

  3. Enter the following JSON payload:

     {
       "username": "admin",
       "password": "password"
     }
    
  4. Click Send and you should receive a response containing a JWT token:

     {
       "token": "your_generated_jwt_token"
     }
    

Step 2: Access the Protected Route

  1. Copy the JWT token from the login response.

  2. Create a GET request to:

     http://localhost:8080/protected
    
  3. Go to the Headers tab and add a new key-value pair:

    • Key: Authorization

    • Value: your_generated_jwt_token

  4. 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!

0
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.