From 55606d43d54bf62e61ce4999710ead9b04af183b Mon Sep 17 00:00:00 2001 From: mathis Date: Fri, 27 Feb 2026 11:08:09 +0100 Subject: [PATCH] refactor logout handling to retrieve EasyCheck URL dynamically from database --- .env | 4 +- config/services.yaml | 3 - docs/SSO_SLO_Documentation.md | 7 +- src/Entity/OAuth2Client.php | 160 ++++++++++++++++++++++ src/EventListener/LogoutSubscriber.php | 19 ++- src/Repository/OAuth2ClientRepository.php | 34 +++++ 6 files changed, 215 insertions(+), 12 deletions(-) create mode 100644 src/Entity/OAuth2Client.php create mode 100644 src/Repository/OAuth2ClientRepository.php diff --git a/.env b/.env index 9d208c7..0f00f8c 100644 --- a/.env +++ b/.env @@ -74,6 +74,4 @@ AWS_ENDPOINT=https://s3.amazonaws.com AWS_S3_PORTAL_URL=https://s3.amazonaws.com/portal ###< aws/aws-sdk-php-symfony ### APP_URL='https://example.com' -APP_DOMAIN='example.com' - -EASYCHECK_URL='https://check.solutions-easy.com' \ No newline at end of file +APP_DOMAIN='example.com' \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 4744596..e00450e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -13,7 +13,6 @@ parameters: logos_directory: '%kernel.project_dir%/public/uploads/logos' oauth_sso_identifier: '%env(OAUTH_SSO_IDENTIFIER)%' oauth_sso_identifier_login: '%env(OAUTH_SSO_IDENTIFIER_LOGIN)%' - easycheck_url: '%env(EASYCHECK_URL)%' services: # default configuration for services in *this* file @@ -62,7 +61,5 @@ services: # please note that last definitions always *replace* previous ones App\EventListener\LogoutSubscriber: - arguments: - $easycheckUrl: '%env(EASYCHECK_URL)%' tags: - { name: kernel.event_subscriber } diff --git a/docs/SSO_SLO_Documentation.md b/docs/SSO_SLO_Documentation.md index 9468805..bdf2344 100644 --- a/docs/SSO_SLO_Documentation.md +++ b/docs/SSO_SLO_Documentation.md @@ -102,7 +102,7 @@ Lorsqu'un utilisateur se déconnecte d'une application, il est **automatiquement └─> Redirection vers EasyCheck 6. EasyPortal → Redirection - └─> GET https://check.../logout + └─> GET {{ easycheck_url }}/logout 7. EasyCheck → Invalide la session └─> Session détruite, cookies supprimés @@ -133,9 +133,6 @@ OAUTH_CLIENT_SECRET='secret-key' ### EasyPortal (.env) ```bash -# URL de l'application cliente (EasyCheck) -EASYCHECK_URL='https://check.solutions-easy.moi' - # Configuration OAuth2 Server OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/jwt/private.key OAUTH_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.key @@ -143,6 +140,8 @@ OAUTH_PASSPHRASE='passphrase' OAUTH_ENCRYPTION_KEY='encryption-key' ``` +**Note** : L'URL d'EasyCheck n'est plus stockée dans une variable d'environnement mais récupérée dynamiquement depuis la table `oauth2_client` en base de données. + ## Points importants ### Sécurité diff --git a/src/Entity/OAuth2Client.php b/src/Entity/OAuth2Client.php new file mode 100644 index 0000000..ad9a3c0 --- /dev/null +++ b/src/Entity/OAuth2Client.php @@ -0,0 +1,160 @@ + false])] + private bool $allowPlainTextPkce = false; + + public function getIdentifier(): ?string + { + return $this->identifier; + } + + public function setIdentifier(string $identifier): self + { + $this->identifier = $identifier; + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + return $this; + } + + public function getSecret(): ?string + { + return $this->secret; + } + + public function setSecret(?string $secret): self + { + $this->secret = $secret; + return $this; + } + + public function getRedirectUris(): ?string + { + return $this->redirectUris; + } + + public function setRedirectUris(?string $redirectUris): self + { + $this->redirectUris = $redirectUris; + return $this; + } + + public function getRedirectUrisArray(): array + { + if (!$this->redirectUris) { + return []; + } + + $decoded = json_decode($this->redirectUris, true); + if (is_array($decoded)) { + return $decoded; + } + + return [$this->redirectUris]; + } + + public function getGrants(): ?string + { + return $this->grants; + } + + public function setGrants(?string $grants): self + { + $this->grants = $grants; + return $this; + } + + public function getScopes(): ?string + { + return $this->scopes; + } + + public function setScopes(?string $scopes): self + { + $this->scopes = $scopes; + return $this; + } + + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): self + { + $this->active = $active; + return $this; + } + + public function isAllowPlainTextPkce(): bool + { + return $this->allowPlainTextPkce; + } + + public function setAllowPlainTextPkce(bool $allowPlainTextPkce): self + { + $this->allowPlainTextPkce = $allowPlainTextPkce; + return $this; + } + + public function getBaseUrl(): ?string + { + $uris = $this->getRedirectUrisArray(); + if (empty($uris)) { + return null; + } + + $firstUri = $uris[0]; + $parsed = parse_url($firstUri); + + if (!isset($parsed['scheme'], $parsed['host']) || !$parsed) { + return null; + } + + $baseUrl = $parsed['scheme'] . '://' . $parsed['host']; + + if (isset($parsed['port']) && !in_array($parsed['port'], [80, 443], true)) { + $baseUrl .= ':' . $parsed['port']; + } + + return $baseUrl; + } +} diff --git a/src/EventListener/LogoutSubscriber.php b/src/EventListener/LogoutSubscriber.php index be38ffa..8443c42 100644 --- a/src/EventListener/LogoutSubscriber.php +++ b/src/EventListener/LogoutSubscriber.php @@ -2,6 +2,7 @@ namespace App\EventListener; +use App\Repository\OAuth2ClientRepository; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -10,7 +11,7 @@ use Symfony\Component\Security\Http\Event\LogoutEvent; class LogoutSubscriber implements EventSubscriberInterface { public function __construct( - private readonly string $easycheckUrl, + private readonly OAuth2ClientRepository $oauth2ClientRepository, private readonly LoggerInterface $logger ) { } @@ -24,7 +25,21 @@ class LogoutSubscriber implements EventSubscriberInterface public function onLogout(LogoutEvent $event): void { - $easycheckLogoutUrl = $this->easycheckUrl . '/logout'; + $easycheckClient = $this->oauth2ClientRepository->findByName('check'); + + if (!$easycheckClient) { + $this->logger->error('OAuth2 client "check" not found in database'); + return; + } + + $easycheckUrl = $easycheckClient->getBaseUrl(); + + if (!$easycheckUrl) { + $this->logger->error('Unable to determine base URL for EasyCheck client'); + return; + } + + $easycheckLogoutUrl = $easycheckUrl . '/logout'; $this->logger->info('LogoutSubscriber triggered - redirecting to EasyCheck logout', [ 'easycheck_logout_url' => $easycheckLogoutUrl, diff --git a/src/Repository/OAuth2ClientRepository.php b/src/Repository/OAuth2ClientRepository.php new file mode 100644 index 0000000..db0ef79 --- /dev/null +++ b/src/Repository/OAuth2ClientRepository.php @@ -0,0 +1,34 @@ +findOneBy(['name' => $name]); + } + + public function findByIdentifier(string $identifier): ?OAuth2Client + { + return $this->findOneBy(['identifier' => $identifier]); + } + + public function findActiveClients(): array + { + return $this->createQueryBuilder('c') + ->where('c.active = :active') + ->setParameter('active', true) + ->getQuery() + ->getResult(); + } +}