package auth import ( "time" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" ) const ( AccessTokenDuration = 15 * time.Minute RefreshTokenDuration = 30 * 24 * time.Hour ) type JWTManager struct { secret []byte } type Claims struct { UserID uuid.UUID `json:"user_id"` jwt.RegisteredClaims } func NewJWTManager(secret string) *JWTManager { return &JWTManager{secret: []byte(secret)} } func (m *JWTManager) GenerateAccessToken(userID uuid.UUID) (string, error) { claims := Claims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(AccessTokenDuration)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(m.secret) } func (m *JWTManager) GenerateRefreshToken(userID uuid.UUID) (string, error) { claims := Claims{ UserID: userID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(RefreshTokenDuration)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(m.secret) } func (m *JWTManager) ValidateToken(tokenString string) (*Claims, error) { token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, jwt.ErrSignatureInvalid } return m.secret, nil }) if err != nil { return nil, err } claims, ok := token.Claims.(*Claims) if !ok || !token.Valid { return nil, jwt.ErrSignatureInvalid } return claims, nil }