Skip to content

AJAX requests fail silently on session timeout instead of redirecting to login #4696

Description

@objecttothis

Problem

When a user's session expires from inactivity, page navigations correctly redirect to the login page. However, AJAX requests (e.g. bootstrap-table server-side search/sort calls) do not — they fail silently or malfunction instead of prompting re-authentication.

Example symptom: on a bootstrap-table list page, clicking a column sort header while the session is expired makes all rows disappear with no error message, giving the impression that sorting itself is broken. The real cause is session expiry, not the sort logic.

Root cause

app/Filters/IsLoggedIn.php is a global filter (applied to all routes except login/migrate) that unconditionally throws a RedirectException when the session is invalid:

public function before(RequestInterface $request, $arguments = null)
{
    $employee = model(Employee::class);

    if (!$employee->is_logged_in()) {
        throw new RedirectException('login');
    }
}

This has no AJAX-awareness. CodeIgniter converts the exception into a plain HTTP 302 redirect to /login for every request type, including XHR calls.

For a normal page navigation this works fine — the browser follows the redirect and shows the login page.

For an AJAX call (e.g. bootstrap-table's server-side search/sort endpoint), the browser's XHR transparently follows the 302 and fetches the login page's HTML as the response body. The calling code expects JSON (e.g. {total, rows}), so parsing fails silently and the table just renders empty. No error is surfaced to the user.

This is not specific to any one page or table — it's a global filter, so it affects every AJAX-backed list/search endpoint in the app.

There is currently no AJAX-aware 401 handling anywhere in the codebase: no isAJAX() check in the auth filter, and no global jQuery ajaxError/ajaxSetup interceptor client-side to catch an auth failure and force a redirect.

Proposed solution

  1. Server-side: In IsLoggedIn::before(), check $request->isAJAX(). If true, return a JSON response with HTTP 401 instead of throwing RedirectException. Keep the existing redirect behavior for normal navigations.
  2. Client-side: Add a global AJAX response handler (e.g. $.ajaxSetup({ statusCode: { 401: ... } }), or a bootstrap-table onLoadError handler) that, on receiving a 401, forces a full-page redirect to the login URL.

This way, an expired session during an AJAX call results in a clear redirect to login rather than a confusing, silent UI failure.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions