Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log a user out of a website when they put their computer to sleep

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:

  • Once you close your laptop boot you to the login screen. So the next time you open the laptop and login, and see the browser you are on the login screen. It doesn't have to happen that quickly, but we need a way to send something to the front end basically telling them to refresh the page, once the session is killed, we set the session lifetime on laravel of 15 minutes.

Some people have suggested in other similar questions:

  • to create a custom web-socket handler
  • To compare the session cookie (in the browser) with the user cookie on the back end.
  • To have a timer running on the front end (we do, it just stops when you close the laptop lid)

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?

like image 887
TheWebs Avatar asked Mar 10 '20 19:03

TheWebs


People also ask

How can a user get logout from a website?

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.

Is it better to log off or sleep?

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.

What is the difference between sleep and lock in computer?

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.

What is the function of log off?

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.


1 Answers

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.

The "session timed out" message

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);


};

Handling session termination on the server side

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:

  • Most Debian based systems do their own GC through a cron job (which works out great for your scenario)
  • Other distros let PHP's default GC mechanism handle it, which is based on a probabilistic outcome from each incoming request to PHP that checks file mtime's on session files and deletes those past their 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).

like image 107
Sherif Avatar answered Sep 28 '22 21:09

Sherif