package middleware import ( "net/http" "strings" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type JWTClaims struct { UserID uint `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } func JWTAuth(secret string) gin.HandlerFunc { return func(c *gin.Context) { auth := c.GetHeader("Authorization") if auth == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing authorization"}) return } parts := strings.SplitN(auth, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid authorization format"}) return } claims := &JWTClaims{} token, err := jwt.ParseWithClaims(parts[1], claims, func(t *jwt.Token) (interface{}, error) { return []byte(secret), nil }) if err != nil || !token.Valid { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) return } c.Set("user_id", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) c.Next() } } func GenerateToken(secret string, userID uint, username, role string, expireHours int) (string, error) { claims := JWTClaims{ UserID: userID, Username: username, Role: role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expireHours) * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(secret)) }