From bcc91a17b4f5522d5beba5fc34fd0f661f4b4eb7 Mon Sep 17 00:00:00 2001 From: rudy Date: Thu, 18 Apr 2024 17:13:42 +0200 Subject: [PATCH] =?UTF-8?q?fix=20(oidc=20timeout)=20#31:=20ajout=20d'une?= =?UTF-8?q?=20r=C3=A8gle=20de=20redirection=20en=20cas=20de=20donn=C3=A9e?= =?UTF-8?q?=20de=20session=20perdue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller/MainController.php | 32 +++++++++++++++++++------------ src/Hydra/HydraService.php | 24 +++++++++++++---------- src/Service/SQLLoginService.php | 11 +++-------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/Controller/MainController.php b/src/Controller/MainController.php index d1f96be..46aef1e 100644 --- a/src/Controller/MainController.php +++ b/src/Controller/MainController.php @@ -6,11 +6,12 @@ use App\Entity\User; use App\Hydra\Client; use App\Hydra\HydraService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Finder\Exception\AccessDeniedException; +use Symfony\Component\HttpFoundation\Session\SessionInterface; class MainController extends AbstractController { @@ -26,7 +27,7 @@ class MainController extends AbstractController } #[Route('/', name: 'app_home')] - public function home(Request $request) + public function home(Request $request): RedirectResponse { return $this->hydra->handleLoginRequest($request); } @@ -34,26 +35,33 @@ class MainController extends AbstractController * Route de Healthcheck (notament pour kubernetes) */ #[Route('/health', name: 'health')] - public function health(Request $request) + public function health(Request $request): Response { return new Response('healthy', 200); } - #[Route('/connect/login-accept', name: 'app_login_accept')] - public function loginAccept(Request $request) + #[Route('/connect/login-accept', name: 'app_login_accept', methods: ['GET'])] + public function loginAccept(Request $request): RedirectResponse { - /** @var User */ $user = $this->getUser(); - $loginAcceptRes = $this->client->acceptLoginRequest($this->session->get('challenge'), [ - 'subject' => $user->getLogin(), - 'remember' => true, - ])->toArray(); + + if (!$user instanceof User) { + throw new AccessDeniedException(); + } + $challenge = $this->session->get('challenge'); + if (!$challenge) { + return new RedirectResponse($this->getParameter('issuer_url')); + } + $loginAcceptRes = $this->client->acceptLoginRequest($challenge, [ + 'subject' => $user->getLogin(), + 'remember' => true, + ])->toArray(); return new RedirectResponse($loginAcceptRes['redirect_to']); } #[Route('/connect/consent', name: 'app_consent')] - public function consent(Request $request) + public function consent(Request $request): RedirectResponse { return $this->hydra->handleConsentRequest($request); } diff --git a/src/Hydra/HydraService.php b/src/Hydra/HydraService.php index e7f47f5..3737833 100644 --- a/src/Hydra/HydraService.php +++ b/src/Hydra/HydraService.php @@ -2,6 +2,7 @@ namespace App\Hydra; +use App\Entity\User; use App\Hydra\Exception\InvalidChallengeException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Exception\BadRequestException; @@ -9,13 +10,14 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Exception\AccessDeniedException; class HydraService extends AbstractController { - public SessionInterface $session; - public Client $client; - public TokenStorageInterface $tokenStorage; - public string $baseUrl; + private SessionInterface $session; + private Client $client; + private TokenStorageInterface $tokenStorage; + private string $baseUrl; public function __construct(Client $client, SessionInterface $session, TokenStorageInterface $tokenStorage, string $baseUrl) { @@ -25,7 +27,7 @@ class HydraService extends AbstractController $this->baseUrl = $baseUrl; } - public function handleLoginRequest(Request $request) + public function handleLoginRequest(Request $request): RedirectResponse { $challenge = $request->query->get('login_challenge'); // S'il n'y a pas de challenge, on déclenche une bad request @@ -37,15 +39,15 @@ class HydraService extends AbstractController $loginRequestInfo = $res->toArray(); if (200 !== $res->getStatusCode()) { $this->session->clear(); - throw new BadRequestException('pas de code 200'); + throw new BadRequestException(); } // si le challenge est validé par hydra, on le stocke en session pour l'utiliser par la suite et on redirige vers une route interne protégée qui va déclencher l'identification FranceConnect $this->session->set('challenge', $loginRequestInfo['challenge']); - return new RedirectResponse($this->baseUrl.'/connect/login-accept'); + return new RedirectResponse($this->baseUrl . '/connect/login-accept'); } - public function handleConsentRequest(Request $request) + public function handleConsentRequest(Request $request): RedirectResponse { $challenge = $request->query->get('consent_challenge'); if (!$challenge) { @@ -53,8 +55,10 @@ class HydraService extends AbstractController } $consentRequestInfo = $this->client->fetchConsentRequestInfo($challenge)->toArray(); - /** @var User */ $user = $this->getUser(); + if (!$user instanceof User) { + throw new AccessDeniedException('Utilisateur non autorisé.'); + } $consentAcceptResponse = $this->client->acceptConsentRequest($consentRequestInfo['challenge'], [ 'grant_scope' => $consentRequestInfo['requested_scope'], 'session' => [ @@ -65,7 +69,7 @@ class HydraService extends AbstractController return new RedirectResponse($consentAcceptResponse['redirect_to']); } - public function handleLogoutRequest(Request $request) + public function handleLogoutRequest(Request $request): RedirectResponse { $logoutChallenge = $request->get('logout_challenge'); if (empty($logoutChallenge)) { diff --git a/src/Service/SQLLoginService.php b/src/Service/SQLLoginService.php index db1c957..16b3d45 100644 --- a/src/Service/SQLLoginService.php +++ b/src/Service/SQLLoginService.php @@ -17,7 +17,7 @@ class SQLLoginService extends AbstractController $this->sqlLoginRequest = $sqlLoginRequest; } - public function fetchDatas($login) + public function fetchDatas(string $login) { try { $dbh = $this->getConnection(); @@ -36,12 +36,7 @@ class SQLLoginService extends AbstractController return $datas; } - /** - * @param mixed $login - * - * @return bool - */ - public function fetchPassword($login) + public function fetchPassword(string $login) { try { $dbh = $this->getConnection(); @@ -57,7 +52,7 @@ class SQLLoginService extends AbstractController return [ $password[$this->sqlLoginRequest->getPasswordColumnName()], isset($password[$this->sqlLoginRequest->getSaltColumnName()]) ? $password[$this->sqlLoginRequest->getSaltColumnName()] : null, - ]; + ]; } return false;