feat: Connexion utilisateur avec sécurité renforcée
Implémente la Story 1.4 du système d'authentification avec plusieurs couches de protection contre les attaques par force brute. Sécurité backend : - Authentification JWT avec access token (15min) + refresh token (7j) - Rotation automatique des refresh tokens avec détection de replay - Rate limiting progressif par IP (délai Fibonacci après échecs) - Intégration Cloudflare Turnstile CAPTCHA après 5 tentatives - Alerte email à l'utilisateur après blocage temporaire - Isolation multi-tenant (un utilisateur ne peut se connecter que sur son établissement) Frontend : - Page de connexion avec feedback visuel des délais et erreurs - Composant TurnstileCaptcha réutilisable - Gestion d'état auth avec stockage sécurisé des tokens - Tests E2E Playwright pour login, tenant isolation, et activation Infrastructure : - Configuration Symfony Security avec json_login + jwt - Cache pools séparés (filesystem en test, Redis en prod) - NullLoginRateLimiter pour environnement de test (évite blocage CI) - Génération des clés JWT en CI après démarrage du backend
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Administration\Infrastructure\Security;
|
||||
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
|
||||
|
||||
/**
|
||||
* Enrichit le payload JWT avec les claims métier.
|
||||
*
|
||||
* Claims ajoutés:
|
||||
* - sub: Email de l'utilisateur (identifiant Symfony Security)
|
||||
* - user_id: UUID de l'utilisateur (pour les consommateurs d'API)
|
||||
* - tenant_id: UUID du tenant pour l'isolation multi-tenant
|
||||
* - roles: Liste des rôles Symfony pour l'autorisation
|
||||
*
|
||||
* @see Story 1.4 - Connexion utilisateur
|
||||
*/
|
||||
final readonly class JwtPayloadEnricher
|
||||
{
|
||||
public function onJWTCreated(JWTCreatedEvent $event): void
|
||||
{
|
||||
$user = $event->getUser();
|
||||
|
||||
if (!$user instanceof SecurityUser) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payload = $event->getData();
|
||||
|
||||
// Claims métier pour l'isolation multi-tenant et l'autorisation
|
||||
$payload['user_id'] = $user->userId();
|
||||
$payload['tenant_id'] = $user->tenantId();
|
||||
$payload['roles'] = $user->getRoles();
|
||||
|
||||
$event->setData($payload);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user