3737use  Glpi \Application \View \TemplateRenderer ;
3838use  Glpi \Exception \AuthenticationFailedException ;
3939use  Glpi \Exception \Http \AccessDeniedHttpException ;
40+ use  Glpi \Exception \Http \HttpException ;
4041use  Glpi \Exception \SessionExpiredException ;
4142use  Glpi \Http \RedirectResponse ;
4243use  Session ;
@@ -62,12 +63,6 @@ public function onKernelException(ExceptionEvent $event): void
6263        }
6364
6465        $ request$ eventgetRequest ();
65- 
66-         if  ($ requestisXmlHttpRequest () || $ requestgetPreferredFormat () !== 'html ' ) {
67-             // Do not redirect AJAX requests nor requests that expect the response to be something else than HTML. 
68-             return ;
69-         }
70- 
7166        $ throwable$ eventgetThrowable ();
7267
7368        $ responsenull ;
@@ -79,18 +74,37 @@ public function onKernelException(ExceptionEvent $event): void
7974            ->getBoolean ('_redirected_from_profile_selector ' )
8075        ;
8176
77+         // Handle SessionExpiredException BEFORE checking if request is AJAX 
78+         // This ensures that expired sessions return proper HTTP 401 response for AJAX requests 
8279        if  ($ throwableinstanceof  SessionExpiredException) {
8380            Session::destroy (); // destroy the session to prevent pesistence of unexpected data 
8481
85-             $ responsenew  RedirectResponse (
86-                 sprintf (
87-                     '%s/?redirect=%s&error=3 ' ,
88-                     $ requestgetBasePath (),
89-                     \rawurlencode ($ requestgetPathInfo () . '? '  . $ requestgetQueryString ())
90-                 )
91-             );
92-         } elseif  (
93-             $ throwableinstanceof  AccessDeniedHttpException
82+             if  ($ requestisXmlHttpRequest () || $ requestgetPreferredFormat () !== 'html ' ) {
83+                 // For AJAX/JSON requests, convert the error into a HttpException 
84+                 $ http_exceptionnew  HttpException (401 , 'Session expired. ' );
85+                 $ http_exceptionsetMessageToDisplay (__ ('Your session has expired. Please log in again. ' ));
86+                 throw  $ http_exception
87+             } else  {
88+                 // For HTML requests, redirect to login page (existing behavior) 
89+                 $ responsenew  RedirectResponse (
90+                     sprintf (
91+                         '%s/?redirect=%s&error=3 ' ,
92+                         $ requestgetBasePath (),
93+                         \rawurlencode ($ requestgetPathInfo () . '? '  . $ requestgetQueryString ())
94+                     )
95+                 );
96+             }
97+         }
98+ 
99+         // Skip AJAX requests for OTHER exceptions (not SessionExpiredException) 
100+         if  ($ responsenull  && ($ requestisXmlHttpRequest () || $ requestgetPreferredFormat () !== 'html ' )) {
101+             // Do not redirect AJAX requests nor requests that expect the response to be something else than HTML. 
102+             return ;
103+         }
104+ 
105+         if  (
106+             $ responsenull 
107+             && $ throwableinstanceof  AccessDeniedHttpException
94108            && $ redirect_to_home_on_error
95109        ) {
96110            $ request$ eventgetRequest ();
@@ -100,7 +114,9 @@ public function onKernelException(ExceptionEvent $event): void
100114                    $ requestgetBasePath ()
101115                )
102116            );
103-         } elseif  ($ throwableinstanceof  AuthenticationFailedException) {
117+         }
118+ 
119+         if  ($ responsenull  && $ throwableinstanceof  AuthenticationFailedException) {
104120            $ login_urlsprintf (
105121                '%s/front/logout.php?noAUTO=1 ' ,
106122                $ requestgetBasePath ()
0 commit comments