116 lines
4.3 KiB
PHP
116 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\EventSubscriber;
|
|
|
|
use App\Entity\User;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;
|
|
use League\Bundle\OAuth2ServerBundle\Model\Client;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
|
|
|
class LoginSubscriber implements EventSubscriberInterface
|
|
{
|
|
|
|
private EntityManagerInterface $entityManager;
|
|
|
|
public function __construct(
|
|
EntityManagerInterface $entityManager,
|
|
private string $clientIdentifier,
|
|
private string $easycheckUrl,
|
|
private LoggerInterface $logger
|
|
)
|
|
{
|
|
$this->entityManager = $entityManager;
|
|
}
|
|
|
|
public static function getSubscribedEvents()
|
|
{
|
|
return [
|
|
LoginSuccessEvent::class => 'onLoginSuccess',
|
|
];
|
|
}
|
|
|
|
public function onLoginSuccess(LoginSuccessEvent $event): void
|
|
{
|
|
$passportUser = $event->getUser();
|
|
|
|
// 1. Check if we have a user at all
|
|
if (!$passportUser) {
|
|
return;
|
|
}
|
|
|
|
// 2. IMPORTANT: Check if this is a real User entity from your DB.
|
|
// If it's a Machine/Client login, it will be an instance of
|
|
// League\Bundle\OAuth2ServerBundle\Security\User\ClientCredentialsUser
|
|
if (!$passportUser instanceof \App\Entity\User) {
|
|
// It's a machine (M2M), so we don't track "last connection" or create manual tokens
|
|
return;
|
|
}
|
|
|
|
// Now we know it's a real human user
|
|
$user = $this->entityManager->getRepository(User::class)->findOneBy([
|
|
'email' => $passportUser->getUserIdentifier()
|
|
]);
|
|
|
|
if ($user) {
|
|
$user->setLastConnection(new \DateTime('now', new \DateTimeZone('Europe/Paris')));
|
|
|
|
$easySolution = $this->entityManager->getRepository(Client::class)->findOneBy(['identifier' => $this->clientIdentifier]);
|
|
if ($easySolution) {
|
|
$accessToken = new AccessToken(
|
|
identifier: bin2hex(random_bytes(40)),
|
|
expiry: new \DateTimeImmutable('+1 hour', new \DateTimeZone('Europe/Paris')),
|
|
client: $easySolution,
|
|
userIdentifier: $user->getUserIdentifier(),
|
|
scopes: ['email', 'profile', 'openid', 'apps:easySolutions']
|
|
);
|
|
$this->entityManager->persist($user);
|
|
$this->entityManager->persist($accessToken);
|
|
$this->entityManager->flush();
|
|
}
|
|
}
|
|
|
|
// Vérifier si un paramètre redirect_app est présent dans l'URL
|
|
$request = $event->getRequest();
|
|
$redirectApp = $request->query->get('redirect_app');
|
|
|
|
if ($redirectApp) {
|
|
$this->logger->info('User logged in with redirect_app parameter', [
|
|
'user' => $user?->getUserIdentifier(),
|
|
'redirect_app' => $redirectApp
|
|
]);
|
|
|
|
// Mapper le nom de l'application vers son URL de connexion SSO
|
|
$appUrls = [
|
|
'easycheck' => $this->easycheckUrl . '/sso/login',
|
|
// Ajouter d'autres applications ici au fur et à mesure
|
|
];
|
|
|
|
if (isset($appUrls[$redirectApp])) {
|
|
$redirectUrl = $appUrls[$redirectApp];
|
|
|
|
$this->logger->info('Redirecting to application after login', [
|
|
'user' => $user?->getUserIdentifier(),
|
|
'app' => $redirectApp,
|
|
'url' => $redirectUrl
|
|
]);
|
|
|
|
$event->setResponse(new RedirectResponse($redirectUrl));
|
|
} else {
|
|
$this->logger->warning('Unknown redirect_app parameter, using default target path', [
|
|
'redirect_app' => $redirectApp,
|
|
'user' => $user?->getUserIdentifier()
|
|
]);
|
|
}
|
|
} else {
|
|
// Pas de paramètre redirect_app : laisser Symfony gérer la redirection par défaut
|
|
$this->logger->info('Normal login - using default target path', [
|
|
'user' => $user?->getUserIdentifier()
|
|
]);
|
|
}
|
|
}
|
|
}
|