function ajax_wrapper(options) {
  // get original callback functions
  var error_original = function(xhr, status, error) {};
  if (options.error) {
    error_original = options.error;
  }
  var complete_original = function(xhr, status) {};
  if (options.complete) {
    complete_original = options.complete;
  }

  // prepare new callback functions
  var options_new = $.extend(true, {}, options);
  // display login dialog on error
  options_new.error = function(xhr, status, error) {
    if (xhr.status == 401) {
      ajax_queue.push(options);
      if (!login_dialog_opened) {
        login_dialog(function() {
          var item;
          while (ajax_queue.length > 0) {
            item = ajax_queue.shift();
            ajax_wrapper(item);
          }
        });
      }
    }
    else {
      error_original(xhr, status, error);
    }
  }
  // Do not run complete function if login dialog is open.
  // Once user is logged in again, the original complete function will be run
  // in repeated ajax call run by login dialog on success.
  options_new.complete = function(xhr, status) {
    if (xhr.status == 401) {
      return;
    }
    else {
      complete_original(xhr, status);
    }
  }

  // run ajax request or put it into a queue
  if (login_dialog_opened) {
    ajax_queue.push(options);
  }
  else {
    $.ajax(options_new);
  }
}
Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions.