Le super admin (table super_admins, master DB) ne pouvait pas se connecter via /api/login car ce firewall n'utilisait que le provider tenant. De même, le JWT n'était pas enrichi pour les super admins, l'endpoint /api/me/roles les rejetait, et le frontend redirigeait systématiquement vers /dashboard. Un chain provider (super_admin + tenant) résout l'authentification, le JwtPayloadEnricher et MyRolesProvider gèrent désormais les deux types d'utilisateurs, et le frontend redirige selon le rôle après login.
50 lines
1.4 KiB
PHP
50 lines
1.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Administration\Infrastructure\Security;
|
|
|
|
use App\SuperAdmin\Infrastructure\Security\SecuritySuperAdmin;
|
|
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
|
|
|
|
/**
|
|
* Enriches the JWT payload with business claims.
|
|
*
|
|
* Added claims:
|
|
* - sub: User email (Symfony Security identifier)
|
|
* - user_id: User UUID (for API consumers)
|
|
* - tenant_id: Tenant UUID for multi-tenant isolation (regular users only)
|
|
* - user_type: "super_admin" for super admins
|
|
* - roles: List of Symfony roles for authorization
|
|
*
|
|
* @see Story 1.4 - User login
|
|
*/
|
|
final readonly class JwtPayloadEnricher
|
|
{
|
|
public function onJWTCreated(JWTCreatedEvent $event): void
|
|
{
|
|
$user = $event->getUser();
|
|
$payload = $event->getData();
|
|
|
|
if ($user instanceof SecuritySuperAdmin) {
|
|
$payload['user_id'] = $user->superAdminId();
|
|
$payload['user_type'] = 'super_admin';
|
|
$payload['roles'] = $user->getRoles();
|
|
$event->setData($payload);
|
|
|
|
return;
|
|
}
|
|
|
|
if (!$user instanceof SecurityUser) {
|
|
return;
|
|
}
|
|
|
|
// Business claims for multi-tenant isolation and authorization
|
|
$payload['user_id'] = $user->userId();
|
|
$payload['tenant_id'] = $user->tenantId();
|
|
$payload['roles'] = $user->getRoles();
|
|
|
|
$event->setData($payload);
|
|
}
|
|
}
|