package services import ( "context" "crypto/sha256" "encoding/hex" "fmt" "time" "github.com/redis/go-redis/v9" ) // TokenBlacklist gère la blacklist de tokens JWT pour invalider les tokens après logout ou révocation // T0174: Service pour gérer la blacklist de tokens avec Redis type TokenBlacklist struct { client *redis.Client prefix string // Préfixe pour les clés Redis (ex: "token_blacklist:") } // NewTokenBlacklist crée une nouvelle instance de TokenBlacklist // T0174: Crée un service TokenBlacklist avec Redis func NewTokenBlacklist(client *redis.Client) *TokenBlacklist { return &TokenBlacklist{ client: client, prefix: "token_blacklist:", } } // Add ajoute un token à la blacklist avec un TTL // T0174: Ajoute un token à la blacklist avec expiration automatique func (tb *TokenBlacklist) Add(ctx context.Context, token string, ttl time.Duration) error { tokenHash := tb.hashToken(token) key := tb.prefix + tokenHash // T0174: Ajouter le token à Redis avec TTL pour expiration automatique err := tb.client.Set(ctx, key, "1", ttl).Err() if err != nil { return fmt.Errorf("failed to add token to blacklist: %w", err) } return nil } // IsBlacklisted vérifie si un token est dans la blacklist // T0174: Vérifie si un token est blacklisté func (tb *TokenBlacklist) IsBlacklisted(ctx context.Context, token string) (bool, error) { tokenHash := tb.hashToken(token) key := tb.prefix + tokenHash // T0174: Vérifier si la clé existe dans Redis exists, err := tb.client.Exists(ctx, key).Result() if err != nil { return false, fmt.Errorf("failed to check token blacklist: %w", err) } return exists > 0, nil } // Remove supprime un token de la blacklist (optionnel, utile pour tests) func (tb *TokenBlacklist) Remove(ctx context.Context, token string) error { tokenHash := tb.hashToken(token) key := tb.prefix + tokenHash err := tb.client.Del(ctx, key).Err() if err != nil { return fmt.Errorf("failed to remove token from blacklist: %w", err) } return nil } // AddTokenHash ajoute un token hash directement à la blacklist (T0206) // Cette méthode permet d'ajouter un tokenHash sans le re-hasher func (tb *TokenBlacklist) AddTokenHash(ctx context.Context, tokenHash string, ttl time.Duration) error { key := tb.prefix + tokenHash // Ajouter le tokenHash à Redis avec TTL pour expiration automatique err := tb.client.Set(ctx, key, "1", ttl).Err() if err != nil { return fmt.Errorf("failed to add token hash to blacklist: %w", err) } return nil } // hashToken hash un token avec SHA-256 pour la sécurité func (tb *TokenBlacklist) hashToken(token string) string { hash := sha256.Sum256([]byte(token)) return hex.EncodeToString(hash[:]) }