package jwt import ( "net/http" "strings" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" "github.com/spf13/viper" ) type Claims struct { UserID uuid.UUID `json:"user_id"` jwt.RegisteredClaims } func JWTAuth() gin.HandlerFunc { var JwtSecret = []byte(viper.GetString("secrets.jwt_secret")) return func(c *gin.Context) { auth := c.GetHeader("Authorization") if auth == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "missing Authorization header", }) return } parts := strings.SplitN(auth, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "invalid Authorization header format", }) return } tokenStr := parts[1] token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) { return JwtSecret, nil }) if err != nil || !token.Valid { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "invalid or expired token", }) return } claims, ok := token.Claims.(*Claims) if !ok { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "invalid token claims", }) return } c.Set("user_id", claims.UserID) c.Next() } } func GenerateToken(userID uuid.UUID, application string) (string, error) { var JwtSecret = []byte(viper.GetString("server.jwt_secret")) claims := Claims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(viper.GetDuration("ttl.jwt_ttl"))), IssuedAt: jwt.NewNumericDate(time.Now()), Issuer: application, }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(JwtSecret) }