From 3c7f035f7aaecc7ef633ae95281eea806428d185 Mon Sep 17 00:00:00 2001 From: Serreau Jovann Date: Tue, 10 Mar 2026 09:11:16 +0100 Subject: [PATCH] fix: prevent HTTP cache from storing OAuth state redirects Add Cache-Control: no-store headers to Keycloak OAuth start routes so the HTTP kernel cache never caches the redirect-with-state response, which caused "Invalid state parameter" errors on subsequent logins. Co-Authored-By: Claude Sonnet 4.6 --- src/Controller/EtlController.php | 8 ++++++-- src/Controller/HomeController.php | 14 +++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Controller/EtlController.php b/src/Controller/EtlController.php index e8ff1e8..7713b47 100644 --- a/src/Controller/EtlController.php +++ b/src/Controller/EtlController.php @@ -1077,11 +1077,15 @@ class EtlController extends AbstractController } #[Route('/etl/connect/keycloak', name: 'connect_keycloak_etl_start')] - public function connectKeycloakEtlStart(ClientRegistry $clientRegistry): RedirectResponse + public function connectKeycloakEtlStart(ClientRegistry $clientRegistry): Response { - return $clientRegistry + $response = $clientRegistry ->getClient('keycloak_etl') ->redirect(['openid', 'profile', 'email']); + $response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate'); + $response->headers->set('Pragma', 'no-cache'); + + return $response; } #[Route('/etl/oauth/sso', name: 'connect_keycloak_etl_check')] diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index cd5514b..c9fc95b 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -26,19 +26,23 @@ class HomeController extends AbstractController { #[Route('/intranet/connect/keycloak', name: 'connect_keycloak_start')] - public function connect(ClientRegistry $clientRegistry) + public function connect(ClientRegistry $clientRegistry): Response { - // Redirects to Keycloak - return $clientRegistry + $response = $clientRegistry ->getClient('keycloak') - ->redirect(['email', 'profile','openid'], []); + ->redirect(['email', 'profile', 'openid'], []); + $response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate'); + $response->headers->set('Pragma', 'no-cache'); + + return $response; } #[Route('/intranet/oauth/sso', name: 'connect_keycloak_check')] - public function connectCheck(Request $request) + public function connectCheck(Request $request): Response { // This method stays empty; the authenticator will intercept it! + return new Response(); } #[Route(path: '/intranet', name: 'app_home', options: ['sitemap' => false], methods: ['GET','POST'])] public function index(AuthenticationUtils $authenticationUtils): Response