This is a bizarre one. We have a Laravel website, and on said site we have a timer per user, where they get 15 minutes of being inactive before being booted.
We do this through a timer that sits on the page in a react component, it works as we want it to, but now we have a new issue: If a user is logged in and shut the lid of their laptop the website should boot them. Banks do this, Schools and Universities do this, Government sites also do this. So it is possible, just not sure how.
We do use web sockets, using laravel-websockets library and Echo. What I would like to see happen is:
Some people have suggested in other similar questions:
The most popular one seems to be using web-sockets, listening for the user to disconnect and then boot them, which is fine and all, but then how do you send a request to a browser thats suspended to then boot them?
I have found requestIdleCallback() But again, I don't think this is what I want if I already have a heartbeat timer on the site. It also doesn't work in all browsers.
I am very lost here on how to accomplish this, the example I can give is:
Log in to your bank, put your computer to sleep, wait 15-20 minutes, awaken the computer, log in and see your bank now has you on the login screen. That's what I want. But I don't know how to accomplish that.
You cant send events to a "sleeping" browser from the back end, and while yes this would have to be a back end solution, how do you update the front end then, so that they are on the logout screen when they reawaken the laptop or computer?
You may have to click your profile picture or username to reveal this option. Look for one of these options near the top-left or top-right section of the browser window or drop-down menu. Clicking that option logs you out of the online account.
Power surges or power drops occurring when a machine is powered by its power adapter are more harmful to a sleeping computer than to one completely shut down. The heat produced by a sleeping machine exposes all components to higher heat more of the time. Computers left on all the time may have a shorter life.
In sleep mode, your laptop basically turns off with data still in RAM. So when you wake up, you can start using the laptop from where you left. If you lock your laptop, it is still switched ON with all applications running. You cannot access them without unlocking.
Sign out: This option will allow the user to exit the operating system while leaving the computer on. This process is also be known as log out, log off or sign off.
First, let's expand on why Banking websites log you out after 15 minutes without activity. It's a PCI requirement for security.
PCI-DSS requirement 8.1.8:
8.1.8 If a session has been idle for more than 15 minutes, require the user to re-authenticate to re-activate the terminal or session.
In order to achieve this the solution is actually far more primitive than you imagine it to be. It neither requires the use of websockets nor knowing anything about the state of the client's machine (sleep or awake or otherwise). All that is required is knowing the time between the current request using that session and last request using the same session and ensuring they are not greater than 15 minutes apart. If they are the user is to be re-authenticated. If they aren't you may proceed with the request.
You're probably then wondering (if it's that simple) how does the session timed out message appear when you put the computer to sleep and wake it back up. This part is deceptively simple.
When the computer is put to sleep the browser actually disconnects all TCP/IP connections which in turn shuts down the event loop in the javascript engine. So timers don't work. But when the browser wakes up again it attempts to refresh some things including the page itself. So when the page is refreshed the request goes back out to the server invoking the server to require the user re-authenticate.
However, this won't account for the javascript message modal (if that's what you're referring to) which some banking websites do. Also not all browsers do a hard refresh on the page in all scenarios. So another approach can be taken. Rather than have a timer in the browser that times out after 15 minutes you can simply store the page load time in javascript as a timestamp and have a 1 second interval time out that compares that timestamp to the computer's current timestamp. If they are more than 15 minutes apart, the session should be terminated.
window.onload = function() {
sessionStart = Date.now();
timer = setInterval(function() {
if (Date.now() - sessionStart > 15 * 60 * 1000) {
clearTimeout(timer);
alert("Session Timed out!");
window.location = "http://www.example.com/login";
}
}, 1000);
};
Even if the computer goes to sleep and the timer stops, the session will eventually time out on the server side (see section below for details) and when the computer wakes up again the timer with a 1 second interval will eventually startup again, invoking the message (as if the user timed out while the computer was asleep). The time lost between the time the computer went to sleep and the time the computer wakes up won't matter as the timestamp will remain in memory. The disconnect between the client and server is unimportant because they don't need to communicate this information in order for the session to be properly terminated on the server side. The server can do its own garbage collection and terminate the session without communication from the client (i.e asynchronously).
Believe it or not Banks don't care about activity inside of the client. They only care about request activity to the server. So if you're wondering how do they keep the session alive for greater than 15 minutes when the user is on the same page for that long, they simply send a AJAX request in the background to refresh the session after asking the user if they still want to continue.
This can be done in the same onload
event callback we used earlier like so:
window.onload = function() {
sessionStart = Date.now();
timer = setInterval(function() {
if (Date.now() - sessionStart > 10 * 60 * 1000) {
if (confirm("Your session is about to timeout. Do you wish to continue?")) {
// send ajax request to refresh session TTL here
// reset the timer
sessionStart = Date.now();
}
} else if (Date.now() - sessionStart > 15 * 60 * 1000) {
clearTimeout(timer);
alert("Session Timed out!");
window.location = "http://www.example.com/login";
}
}, 1000);
};
To handle the session termination on the server side there are several approaches. Depending on which one you use you will need different tactics. One is using PHP's default session handler and setting the session.max_lifetime
to expire after 15 minutes (this deletes the session data entirely on the server side thus invalidating the client's cookie).
If you let the default session handler mechanism do it you can run into issues depending on which handler is used (files, memcached, redis, custom, etc).
With the files (default handler) the garbage collection happens in one of two ways:
session.max_lifetime
. The problem with this approach is that on low-traffic sites a session could potentially sit there on the server for a long time until enough requests come in (depending on the session.gc_probability
score) to invoke the GC to clean up the session files.With memcached and redis based handlers you don't have this problem. They will handle purging the memory automatically. Sessions may still remain in physical memory for a time past their lifetime, but the daemon will not be able to access them. If you're concerned about this bit for security you can encrypt your sessions at rest or find a key/value store that has stricter memory purging GC mechanism.
With a custom session handler you will have to build your own GC mechanism. Through SessionHandlerInterface
you'd implement a gc
method that hand you the session's maximum lifetime interval and you'd be responsible for verifying if the session has passed its lifetime based on this interval and do your garbage collection from there.
You can also setup a separate end-point that checks the session TTL (via asynchronous AJAX request on the client side) and sends back a response if the session has expired (forcing the javascript to re-authenticate the user).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With