Link to home
Start Free TrialLog in
Avatar of Mark Willis
Mark WillisFlag for United States of America

asked on

How do I keep a JWT session alive as long as the user is active?

I know how to set a fixed session length in both JWT and the $_SESSION cookie. I'm using the session cookie to pass the JWT when a page loads.
How do I reset the session countdown timer back to its initial value every time a page is loaded?
IOW, if the session length is defined as 15 minutes, I want the session to remain alive so long as the user is active no matter how long that may take. I only want the session to timeout 15 minutes after the user stops loading pages.

Thanks!
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

The default Session timeout for PHP is 1440 seconds which is 24 minutes.  PHP sessions work ONLY if you put session_start() at the top of every page.
You said, "I want the session to remain alive so long as the user is active no matter how long that may take."

Considerations...

1) What you mean by active, how long with no activity means session is inactive.

Might be a few minutes, hours, days.

2) A good way to implement this is using AJAX, so once Javascript starts running on the page, a heartbeat flows back to the server per some time interval.

So long as a person is on the page, Javascript keeps running, AJAX calls continue periodically.

When a person leaves the page or pulls the power cord or otherwise terminates their activity, the AJAX calls stop, so then you might consider this inactive.

3) Might be useful for you to dig into the WordPress session management code to see how WordPress handles this.
Maintain your own session data. In a database create a session table that is indexed by the token (or a unique unguessable value obtained from the token)

When a page is accessed - retrieve the token - check the session is valid and at the same time update the last accessed time.

Validation is always
current_time - last_accessed_time < allowed_session_time.

Open in new window


Avatar of Mark Willis

ASKER

To clarify how activity is to be measured, any page load restarts the timer. If another page load (refreshing that same page or navigating to another one) does not occur within the time limit, the user is logged out. Time limit = 1 hour because people are viewing courses online and each video is 50 minutes
"Time limit = 1 hour" is a different sort of problem.  Are you on shared hosting?  If so, it is next to impossible to change the PHP session timeout because it is usually determined by the shortest timeout on any site on that host.  I think AJAX timer and requests is the way to go because then it won't depend on the PHP session timer.
@Mark, that is how I understood it.

Basically you want to check the session (using the token as a key) to see if the current_date - last_accessed time > 1 hour and if so the session has expired.

My approach is to put this logic in a separate file (secure.php) and include it on all pages that are secure.

[secure.php]
<?php
$token = $_COOKIE['token_id'] ?? false;

if ($token) {
  // Assume $db is a PDO object created in the parent script
  // before including secure.php

  $refreshed = Session::refreshToken($db, $token);
}

if (!$token || !$refreshed) {
  header('location: login.html');
  die();
}

Open in new window


[session.php]
class Session {
  // ...
  // .. Other Session functions excluded for brevity
  // ...

  public static function refreshToken($db, $token) {
    $query = <<< QUERY
UPDATE `tblSession`
SET
  `last_accessed` = NOW()
WHERE
  `token` = :token AND
  DATE_ADD(`last_accessed`, INTERVAL 1 HOUR) < NOW()
QUERY;

    $stmt = $db->prepare($query);

    if ($stmt->execute(['token' => $token])) {
      return $stmt->rowCount() > 0;
    }
    return false;
  }
}

Open in new window

Sorry it's taken so long to respond. No, Dave Baldwin, we are not on shared hosting. We have a dedicated server.

Julian Hansen, I kinda see where you are heading with this, but am struggling with how to integrate this with my JWT session token. Based upon what you suggested, I'm thinking I could add the last_refreshed timestamp to the JWT I'm already passing?


ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial