package services import ( "errors" "time" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" ) type JWTService struct { secretKey []byte tokenDuration time.Duration } type TokenClaims struct { UserID string `json:"user_id"` PubKey string `json:"pub_key"` jwt.RegisteredClaims } func NewJWTService(secretKey string, tokenDuration time.Duration) *JWTService { return &JWTService{ secretKey: []byte(secretKey), tokenDuration: tokenDuration, } } // GenerateToken crée un nouveau JWT pour un utilisateur func (s *JWTService) GenerateToken(userID uuid.UUID, pubKey string) (string, error) { now := time.Now() claims := TokenClaims{ UserID: userID.String(), PubKey: pubKey, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(now.Add(s.tokenDuration)), IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(s.secretKey) if err != nil { return "", err } return tokenString, nil } // ValidateToken vérifie la validité d'un JWT et retourne les claims func (s *JWTService) ValidateToken(tokenString string) (*TokenClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) { // Vérifier que la méthode de signature est bien HMAC if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, errors.New("méthode de signature invalide") } return s.secretKey, nil }) if err != nil { return nil, err } if claims, ok := token.Claims.(*TokenClaims); ok && token.Valid { return claims, nil } return nil, errors.New("token invalide") } // RenewToken renouvelle un token existant (si valide et proche de l'expiration) func (s *JWTService) RenewToken(tokenString string) (string, error) { claims, err := s.ValidateToken(tokenString) if err != nil { return "", err } // Créer un nouveau token avec les mêmes informations userID, err := uuid.Parse(claims.UserID) if err != nil { return "", err } return s.GenerateToken(userID, claims.PubKey) } // ExtractUserID extrait l'ID utilisateur d'un token (sans validation complète) func (s *JWTService) ExtractUserID(tokenString string) (string, error) { claims, err := s.ValidateToken(tokenString) if err != nil { return "", err } return claims.UserID, nil }