package middleware import ( "net/http" "strings" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type Claims struct { UserID string `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } func IssueToken(secret, userID, username, role string, ttl time.Duration) (string, error) { c := Claims{ UserID: userID, Username: username, Role: role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(ttl)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } t := jwt.NewWithClaims(jwt.SigningMethodHS256, c) return t.SignedString([]byte(secret)) } func JWTAuth(secret string) gin.HandlerFunc { return func(c *gin.Context) { h := c.GetHeader("Authorization") if h == "" { h = c.Query("token") } const prefix = "Bearer " if strings.HasPrefix(h, prefix) { h = strings.TrimPrefix(h, prefix) } if h == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"}) return } claims := &Claims{} _, err := jwt.ParseWithClaims(h, claims, func(t *jwt.Token) (interface{}, error) { return []byte(secret), nil }) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) return } c.Set("user_id", claims.UserID) c.Set("user", claims.Username) c.Set("role", claims.Role) c.Next() } }