Skip to content

Commit 046ea30

Browse files
authored
fix: return 401 instead of 500 for AJAX requests with expired session
1 parent 4f1277d commit 046ea30

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

src/Glpi/Kernel/Listener/ExceptionListener/AccessErrorListener.php

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
use Glpi\Application\View\TemplateRenderer;
3838
use Glpi\Exception\AuthenticationFailedException;
3939
use Glpi\Exception\Http\AccessDeniedHttpException;
40+
use Glpi\Exception\Http\HttpException;
4041
use Glpi\Exception\SessionExpiredException;
4142
use Glpi\Http\RedirectResponse;
4243
use Session;
@@ -62,12 +63,6 @@ public function onKernelException(ExceptionEvent $event): void
6263
}
6364

6465
$request = $event->getRequest();
65-
66-
if ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== '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 = $event->getThrowable();
7267

7368
$response = null;
@@ -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 ($throwable instanceof SessionExpiredException) {
8380
Session::destroy(); // destroy the session to prevent pesistence of unexpected data
8481

85-
$response = new RedirectResponse(
86-
sprintf(
87-
'%s/?redirect=%s&error=3',
88-
$request->getBasePath(),
89-
\rawurlencode($request->getPathInfo() . '?' . $request->getQueryString())
90-
)
91-
);
92-
} elseif (
93-
$throwable instanceof AccessDeniedHttpException
82+
if ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== 'html') {
83+
// For AJAX/JSON requests, convert the error into a HttpException
84+
$http_exception = new HttpException(401, 'Session expired.');
85+
$http_exception->setMessageToDisplay(__('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+
$response = new RedirectResponse(
90+
sprintf(
91+
'%s/?redirect=%s&error=3',
92+
$request->getBasePath(),
93+
\rawurlencode($request->getPathInfo() . '?' . $request->getQueryString())
94+
)
95+
);
96+
}
97+
}
98+
99+
// Skip AJAX requests for OTHER exceptions (not SessionExpiredException)
100+
if ($response === null && ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== '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+
$response === null
107+
&& $throwable instanceof AccessDeniedHttpException
94108
&& $redirect_to_home_on_error
95109
) {
96110
$request = $event->getRequest();
@@ -100,7 +114,9 @@ public function onKernelException(ExceptionEvent $event): void
100114
$request->getBasePath()
101115
)
102116
);
103-
} elseif ($throwable instanceof AuthenticationFailedException) {
117+
}
118+
119+
if ($response === null && $throwable instanceof AuthenticationFailedException) {
104120
$login_url = sprintf(
105121
'%s/front/logout.php?noAUTO=1',
106122
$request->getBasePath()

0 commit comments

Comments
 (0)