package security import ( "fmt" "strconv" "time" "backupx/server/internal/model" "github.com/golang-jwt/jwt/v5" ) type Claims struct { Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } type JWTManager struct { secret []byte expiry time.Duration } func NewJWTManager(secret string, expiry time.Duration) *JWTManager { return &JWTManager{secret: []byte(secret), expiry: expiry} } func (m *JWTManager) Generate(user *model.User) (string, error) { now := time.Now().UTC() claims := Claims{ Username: user.Username, Role: user.Role, RegisteredClaims: jwt.RegisteredClaims{ Subject: strconv.FormatUint(uint64(user.ID), 10), IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(now.Add(m.expiry)), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(m.secret) } func (m *JWTManager) Parse(tokenString string) (*Claims, error) { token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (any, error) { if token.Method != jwt.SigningMethodHS256 { return nil, fmt.Errorf("unexpected signing method: %s", token.Method.Alg()) } return m.secret, nil }) if err != nil { return nil, err } claims, ok := token.Claims.(*Claims) if !ok || !token.Valid { return nil, fmt.Errorf("invalid token claims") } return claims, nil }