veza/veza-backend-api/internal/services/token_blacklist.go
2025-12-03 20:29:37 +01:00

90 lines
2.7 KiB
Go

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[:])
}