Force user to log-off using pure JavaScript

How can I force user to log out or rather, inform PHP session system, that user is logged-out?

Of course I can simply redirect user to logout action like this:


window.location.href = "/app_www/account/logout.html";

But I want to display some message (JavaScript alert), telling the user, that session has expired and he’ll be logged-off right after clicking OK.

And here is the problem, because, if user is smart enough to hit F5 (reload page) after he sees message, everything goes hell, as he is back on the same page and still logged in.

So I need a permanent solution, that I call before showing the message, that will ensure me, that even, if user reload page, he’ll be logged-off.

EDIT: I must add, that this problems is related to Firefox only. As this is only know to me browser that displays some strange alert-box-replacements that are not true modal message boxes. Both Internet Explorer and Chrome are showing modal dialog boxes, which means that user can’t reload page, by pressing F5, if he has such dialog box displayed on screen.

Make an ajax call to that same page in the background when you want to log them off. On success show the pop-up, on failure, send them to that page just to make sure.

Edit: You could also delete the cookie holding the PHP Session ID to be sure as well

I’m not sure if you can access the PHP cookies using JS, but if that’s possible, you could use a function to check the login status and run it every 10 sec or so. (ajax call would also work, but it creates a lot of requests)

Yes, but how to get name of that cookie and ensure that I’m deleting the right one? It seems that PHP generates session cookie with some random name.

Thanks for the idea, but I would like to avoid AJAX here as much as I can. I would rather like to not rely on this in such delicate situations like user must be 100% logged off. I wonder how it is solved in banks for example?

This problem can also be solved (I thinks so) by logging user on Yii side with duration set to the very same time amount as used in JavaScript. This way, even if user press F5 and reload the page, Yii should notice that login-state cookie has expired (login time has passed) and logoff user automatically.

I’ve played just a little bit with this, but found that either I’m missing something or doing something wrong or this is not working. I’m setting login duration with the same time as I use in JavaScript (60 seconds now, for testing purposes) but after time has really passed out and after pressing F5 user is still logged in.

So hire is slightly different question. Can I somehow read out of CWebUser data information, what duration was passed during login? Just for testing, if everything is OK?

I think using timers to control a logged in status is an even more delicate solution because there are a lot of things that can go wrong. JS uses the local time of the user, PHP uses server time, so you’re dealing with timezones, user settings, browser interpretations, etc.

If big companies like google are using the ajax-method, I guess that’s still the best way, altough not perfect.

I would prefer to keep the login status at one central location (PHP) and use JS to check that.

Like I said, if it’s possible to read PHP cookies with JS, that would be the simplest solution I guess.

Another idea that I just had; on every pageload, you could echo the amount of seconds the current session remains valid, and use a JS timer to countdown, that way, you’re not dealing with JS time settings.

You said in your OP that you wanted pure javascript, but if thats not the case then you might just want to set a time against the session (or even the database for logging purposes) to say when the user logged on. When they hit a page, their logged in status is determined by the presence of a cookie pointing to a session ID which says they are (having filled out a login form) and the stored time that they logged in was not more than 10 minutes ago.

This way whenever they hit a page, it’s checked to make sure they get logged off after 10 minutes, regardless of what javascript happens, but you can still implement a simple alert client side to tell users.

If you wanted to log them off after only 10 minutes of inactivity then you need to update the stored time every time they hit a page and are still successfully logged in.

Re the cookies: you don’t actually access PHP Session data from the client (that would be bad) but you can delete the stored ID, the cookie will be created with whatever name either you php or yii config is set too, defaults to PHPSESSID

No, because I’m doing exactly, as you wrote at the bottom! :] I’m counting starttime (once per page load) and then current time (each time watchdog-function is called, every one second). Subtracting first value from second gives me number of second user has spent on current page after load. I then subtract this value from variable holding session length and get how many seconds left before auto-loggoff. This gives me ability to operate on absolute time periods, without need to take care about mentioned timezones or user tweaking up his local clock.

I agree with you. But I have to check, if session has expired every second and you wrote yourself, that doing this via AJAX would generate really huge number of AJAX call, probably most of them overlapping each other, as most of them will not return result earlier than within one second. This is why I’m going to test AJAX approach as last solution, if all before fails.

Deleting cookies created by PHP via JavaScript is not a problem, as both cookies are stored in the same table of cookies. The problem is, which cookie should I delete? I’ve analysed my page (run on localhost) with Firefox’s Page Info tool and found out that I have three cookies there. One is my own, second is PHPSESSID and third one is 7cf7ec42ac8564e6f334f68be7958d5c, which seems to be some random-generated cookie name. The only cookie I can delete is PHPSESSID, because I will not have access to second one, as it’s name is auto-generated and upon next user logon will probably have different name.

You don’t really need to check weather the user is logged in every second, you only need to know if they’re logged in when they request a page (whether via ajax or browser refresh or link). So only check the time when they hit the page, this cuts down a lot on processing and as long as you store the time that they logged in or were last active you know when to expire their session.

The javascript alert is only a fluff piece of helpfulness to let the user know they’ve been logged off, and if it breaks and doesn’t show for some reason (timer nastyness, javascript disabled, someone being malicious) it won’t matter security wise as the server will know they’re not logged in by it’s own facilities.

Storing (and checking) this information in DB is good idea, but currently I can’t implement it (different issue - PHP is unable to store date and time in Oracle’s DATE column type). And what about logging user off after some fixed period of time, if connection to database would be down at the moment of checking? Whole mechanism would fail?

With this above, you enlighten me to the correct solution! :] I solve the problem with two additional lines of code:


Yii::app()->clientScript->registerCoreScript('cookie');

before registering my auto-logoff-java-script-function and:


$.cookie("'.(Yii::app()->session->sessionName).'", "");

inside this function, right before displaying alert saying that session has expired.

That is all. Thank you.

BTW: I must underline again, that this problem is related to Firefox only. Other browsers tested by me (Internet Explorer and Chrome) does are not affected by this problem as after seeing alert message user is unable to press F5 or refresh a page (or do anything else) before clicking "OK" or hitting "Enter" or "ESC". Any any of these will cause next line of script to be executed, which will log him off and redirect him to login page.

EDIT: [i]I also found that duration set during login process of a user (in LoginForm’s login() function) is not the same as session’s timeout (that was not obvious to me). I have first one now set to 60 seconds (forced by me) and Yii::app()->session->timeout still reports default value of 1440 seconds.

[/i]

a.) Could you not store the time in an integer format as a timestamp? (Number of seconds since epoch)

B.) If the database is down your check of whether the user even exists would fail so surely a page load wouldn’t return user sensitive information anyway.

c.) If the DB really is a problem, store the last time time the user was seen in PHP’s session data, that way it’ll always be there whenever a user is legitimately logged on and browsing. If theres no time there, assume they’re not logged on. On logout, destroy the session.

If someone is still looking for an answer to this, the solution is simple from my perspective:

The solution is not to display a message telling the user: "You will be logged out after clicking OK".

It’s a better idea to do the logout proccess first, and then display a message: “You have been logged out”.

You can logout a user with:


Yii::app()->user->logout();