Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 34 additions & 16 deletions src/Glpi/Kernel/Listener/ExceptionListener/AccessErrorListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
use Glpi\Http\RedirectResponse;
use Session;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
Expand All @@ -62,12 +63,6 @@ public function onKernelException(ExceptionEvent $event): void
}

$request = $event->getRequest();

if ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== 'html') {
// Do not redirect AJAX requests nor requests that expect the response to be something else than HTML.
return;
}

$throwable = $event->getThrowable();

$response = null;
Expand All @@ -79,18 +74,39 @@ public function onKernelException(ExceptionEvent $event): void
->getBoolean('_redirected_from_profile_selector')
;

// Handle SessionExpiredException BEFORE checking if request is AJAX
// This ensures that expired sessions return proper HTTP 401 response for AJAX requests
if ($throwable instanceof SessionExpiredException) {
Session::destroy(); // destroy the session to prevent pesistence of unexpected data

$response = new RedirectResponse(
sprintf(
'%s/?redirect=%s&error=3',
$request->getBasePath(),
\rawurlencode($request->getPathInfo() . '?' . $request->getQueryString())
)
);
} elseif (
$throwable instanceof AccessDeniedHttpException
if ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== 'html') {
// For AJAX/JSON requests, return a JSON response with 401 status
$response = new JsonResponse([
'error' => __('Your session has expired'),
'message' => __('Please log in again'),
'code' => 'ERROR_SESSION_EXPIRED',
], 401);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing back a HttpException should permit to have it correctly handled by the ErrorController.

Suggested change
// For AJAX/JSON requests, return a JSON response with 401 status
$response = new JsonResponse([
'error' => __('Your session has expired'),
'message' => __('Please log in again'),
'code' => 'ERROR_SESSION_EXPIRED',
], 401);
// For AJAX/JSON requests, convert the error into a HttpException
$http_exception = new \Glpi\Exception\Http\HttpException(403, 'Session expired.');
$http_exception->setMessageToDisplay(__('Your session has expired. Please log in again.'));
throw $http_exception;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed here 2d6d33b but i kept 401 Response Code.

} else {
// For HTML requests, redirect to login page (existing behavior)
$response = new RedirectResponse(
sprintf(
'%s/?redirect=%s&error=3',
$request->getBasePath(),
\rawurlencode($request->getPathInfo() . '?' . $request->getQueryString())
)
);
}
}

// Skip AJAX requests for OTHER exceptions (not SessionExpiredException)
if ($response === null && ($request->isXmlHttpRequest() || $request->getPreferredFormat() !== 'html')) {
// Do not redirect AJAX requests nor requests that expect the response to be something else than HTML.
return;
}

if (
$response === null
&& $throwable instanceof AccessDeniedHttpException
&& $redirect_to_home_on_error
) {
$request = $event->getRequest();
Expand All @@ -100,7 +116,9 @@ public function onKernelException(ExceptionEvent $event): void
$request->getBasePath()
)
);
} elseif ($throwable instanceof AuthenticationFailedException) {
}

if ($response === null && $throwable instanceof AuthenticationFailedException) {
$login_url = sprintf(
'%s/front/logout.php?noAUTO=1',
$request->getBasePath()
Expand Down