Table of Contents
Implementing JWT (JSON Web Token) authentication in a Gin web application enhances security by ensuring that only authenticated users can access protected resources. This tutorial provides a step-by-step guide to integrating JWT authentication into your Gin project.
Prerequisites
- Go programming language installed (version 1.16+)
- Basic knowledge of Gin framework
- Understanding of JWT concepts
- Text editor or IDE of your choice
Step 1: Initialize Your Gin Project
Create a new directory for your project and initialize a Go module:
mkdir gin-jwt-auth
cd gin-jwt-auth
go mod init github.com/yourusername/gin-jwt-auth
Install Gin and JWT libraries:
go get -u github.com/gin-gonic/gin
go get -u github.com/dgrijalva/jwt-go
Step 2: Create Main Application File
Create a file named main.go and set up a basic Gin server:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/login", login)
r.GET("/protected", authMiddleware(), protectedEndpoint)
r.Run(":8080")
}
Step 3: Implement Login Handler
The login handler authenticates users and issues JWT tokens:
import (
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
)
var jwtKey = []byte("your_secret_key")
type Credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
func login(c *gin.Context) {
var creds Credentials
if err := c.BindJSON(&creds); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// Replace with real authentication
if creds.Username != "admin" || creds.Password != "password" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
expirationTime := time.Now().Add(15 * time.Minute)
claims := &jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
Subject: creds.Username,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not generate token"})
return
}
c.JSON(http.StatusOK, gin.H{"token": tokenString})
}
Step 4: Create Authentication Middleware
The middleware verifies JWT tokens for protected routes:
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing token"})
return
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, jwt.ErrSignatureInvalid
}
return jwtKey, nil
})
if err != nil || !token.Valid {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
return
}
c.Next()
}
}
Step 5: Create Protected Route
Define a route that requires authentication:
func protectedEndpoint(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Welcome to the protected route!"})
}
Step 6: Run Your Application
Build and run your Gin server:
go run main.go
Test the login endpoint with a POST request containing JSON credentials, then use the returned token to access the protected route by including it in the Authorization header.
Conclusion
By following these steps, you have integrated JWT authentication into your Gin web application. This setup provides a robust security layer, ensuring that only authenticated users can access sensitive resources. Remember to keep your secret keys secure and consider implementing token refresh mechanisms for production environments.