90 lines
2.7 KiB
Go
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[:])
|
|
}
|