package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "github.com/rs/zerolog/log" ) // AuthMiddleware creates a middleware for JWT authentication func AuthMiddleware(jwtSecret string) gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header is required"}) c.Abort() return } parts := strings.Split(authHeader, " ") if len(parts) != 2 || parts[0] != "Bearer" { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header format must be Bearer {token}"}) c.Abort() return } token, err := jwt.Parse(parts[1], func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, jwt.ErrSignatureInvalid } return []byte(jwtSecret), nil }) if err != nil { log.Error().Err(err).Msg("Failed to parse token") c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) c.Abort() return } if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { c.Set("user_id", claims["sub"]) c.Set("user_role", claims["role"]) c.Next() } else { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) c.Abort() return } } } // RoleMiddleware creates a middleware for role-based authorization func RoleMiddleware(roles ...string) gin.HandlerFunc { return func(c *gin.Context) { userRole, exists := c.Get("user_role") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "User role not found"}) c.Abort() return } roleStr, ok := userRole.(string) if !ok { c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user role type"}) c.Abort() return } for _, role := range roles { if role == roleStr { c.Next() return } } c.JSON(http.StatusForbidden, gin.H{"error": "Insufficient permissions"}) c.Abort() } }