0

Issue: Common sense would tell me that anything that actively interacts with the session would constitute session activity and would reset the inactivity timer that determines session timeout and destruction. That has not been my experience. I am trying to determine whether I have a fundamental misunderstanding in the way that sessions work or I have an esoteric bug in my code that is causing me to question the fundamentals of PHP sessions.

Context: I am implementing persistent logins for users of my web application. I've been trying to figure out what determines session inactivity/timeout for several days now, to no avail. I have scoured Stack Overflow and the internet at large (including most of the PHP documentation on sessions), and I still feel like I'm poking at this thing with a stick.

As far as I can tell, "Remember me" cookies, cross-referenced with database entries for user look-ups, are the preferred method of keeping users logged in to an application over periods of inactivity and the closing of their logged-in browser instance. I accept that, and I believe I know how to do it (there is a lot of good information online about the myriad approaches for this).

However, I initially tried to shortcut the moderate amount of work entailed in this approach by simply tweaking some session config parameters, namely: cookie_lifetime and gc_maxlifetime. I expected that increasing these parameters would increase the amount of time it took for the session to timeout, but that was not the case. I set both parameters to 1 year, and the session still timed out after about 40 minutes (which is also weird; everything I've discovered online indicates that 24 minutes is the default timeout).

Next, I tried to sidestep the inactivity thing altogether, and I added a "heartbeat" ajax request that pinged the server every 10 minutes, regenerating the session id and arbitrarily modifying a session key/value store. That experiment yielded the same 40 minute timeout result, with the ajax call consistently failing on its 4th call.

Here's some [simplified] code in case I'm looking in the wrong places for the source of my issue:

/* initialize_session.php (called at the beginning of every php file) */
$heartbeat_timer = 60 * 10; // 10 minutes.
if(session_id() == '' || !isset($_SESSION)){
  # Some of these are already the defaults, but I'm being explicit to avoid ambiguity.
  $session_params = array(
    # Ensure that session file persists beyond heartbeat for keeping alive.
    "gc_maxlifetime" => $heartbeat_timer + 60,
    "cookie_lifetime" => 0,
    "cookie_path" => "/",
    "cookie_domain" => "shhhh.com",
    "use_strict_mode" => TRUE,
    "cookie_secure" => TRUE,
    "cookie_httponly" => TRUE,
    "use_cookies" => TRUE,
    "use_only_cookies" => TRUE,
  );
  session_start($session_params);
}


/* any_page.php (html page where "inactivity" & timeout occur) */
<?php require_once __DIR__ . "/initialize_session.php"; ?>
<body>
  blah blah blah
  <script>
    setInterval(function(){
      $.ajax({
        "url": "keep_alive.php",
        "type": "POST",
        "error": function(xhr, text_status, error_thrown){
          // Log error stuff (incidentally, not helpful).
        }
      });
    }, 600000/* 10 minutes in msec */);
  </script>
</body>


/* keep_alive.php (arbitrary session modification to trick app into thinking I'm active) */
require_once __DIR__ . "/initialize_session.php";
session_regenerate_id(TRUE);
$_SESSION["last_heartbeat"] = time();

It may be worth noting that both the server file store for the session file and the client cookie for the session id are correctly updating per the regenerated session id every 10 minutes. The ajax interval just starts to fail on the 4th request (as I said, consistent with session inactivity timeout prior to all of the experimentation).

halfer
  • 19,824
  • 17
  • 99
  • 186
SheffDoinWork
  • 743
  • 2
  • 8
  • 19
  • I've read your question twice, and still am not sure what you're asking. – Neville Kuyt Aug 02 '18 at 15:47
  • Possible duplicate of [How do I expire a PHP session after 30 minutes?](https://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes) – No Name Aug 02 '18 at 15:49
  • Lol, alright, let me try to be more concise: what determines when a session times out in a PHP web application? If I don't touch a web page for 40 minutes, it times out. I expect that. If I have an interval that changes the session every 10 minutes, the session still times out after 40 minutes. I do not expect that. – SheffDoinWork Aug 02 '18 at 15:49
  • @BojanSrbinoski, I don't think it's a duplicate. I've been on that question and several others like it. I'm asking specifically about this line: "Updating the session data with every request also changes the session file's modification date so that the session is not removed by the garbage collector prematurely." My application is clearing the session information on the client after 40 minutes, even with the modification of session data every 10 minutes. – SheffDoinWork Aug 02 '18 at 15:52
  • It is TIME Of Inactivity. Each new activity resets the clock back to zero – RiggsFolly Aug 02 '18 at 15:55
  • Perhaps I'm confused on what constitutes "new activity". Could you clarify what PHP interprets as new activity? – SheffDoinWork Aug 02 '18 at 15:57
  • In your case a call to `session_start()` – RiggsFolly Aug 02 '18 at 15:58
  • I am calling that every 10 minutes via the `keep_alive` and `initialize_session` scripts, though. And wouldn't id regeneration/session value modification also qualify as new activity? – SheffDoinWork Aug 02 '18 at 16:00
  • Try to set `session.gc_probability` & `session.gc_divisor` in `php.ini` as you prefer though not that much reliable. Reference: http://php.net/manual/en/session.configuration.php#ini.session.gc-probability You can always write your own function to destroy the session as you need. Try to determine user activity but not session activity to set a lifetime for your session. – Klanto Aguntuk Aug 02 '18 at 17:30

2 Answers2

2

Allow me to propose a different approach to consider.

I wouldn't depend on PHP settings to get consistent results since even understanding how all those options work together is a daunting task.

I'd (on the server side, in your app) store the last activity timestamp together with the session ID (the one stored in the cookie). You can then use it to know if you still want to keep your user logged in or not. And you can update this entry in the heartbeat if you want. Then you can set up PHP configs to have long timeouts for the session.

It would make it easier to debug, and later - if you wanted to implement a warning alert ("You'll be logged out in 10, 9, 8...") it would be easier as well.

Greg
  • 5,862
  • 1
  • 25
  • 52
0

From what everyone has contributed in the comments to my question, I am fairly certain there is a bug in my application and it just did a number on my understanding of session fundamentals. My assumptions regarding session inactivity and timeout appear to be correct. I'll edit my question and this answer once I get to the bottom of the issue.

SheffDoinWork
  • 743
  • 2
  • 8
  • 19