Auto-loggoff user, if session time has passed

I’m continuing my plays with JavaScript and time functions (after this article). If you want to log-off user after some predefined time has passed, you can do this for example with below presented solution.

Auto-logging-off function

A simple watchdog-like function:

var startTime = new Date();
var intervalID = window.setInterval(sessionTimeoutWatchdog, 1000);

function sessionTimeoutWatchdog()
{
    var timerDiv = document.getElementById("timer");
    var currentTime = new Date();
    var autologoffTime = 360;

    var differenceTime = autologoffTime - Math.round((currentTime - startTime) / 1000);
    var differenceDate = (differenceTime * 1000) - 3600000; //Fix for Date object...
    differenceDate = new Date(differenceDate);

    timerDiv.innerHTML = formatTime(differenceDate, "HH:MM:SS");

    if(differenceTime < = 0)
    {
		  clearInterval(intervalID);

		  alert("Session has expired! You'll be reidrected to login screen...");

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

After seeing that message, user can either click OK, close the dialog box, hit Enter or ESC. No matter, what he’ll do, next script line is executed and he’s redirected to logout page.

Problems with Firefox

Notice, that this works fine in all web browsers except in Firefox. This is the only browser, which displays alert boxes as non-modal (i.e. they can be ignored by pressing F5 and reloading whole page). So, for Firefox only, to avoid this, you must delete cookie that holds your visitor’s login-state, just before displaying alert message.

If you are using jQuery with jQuery Cookie plugin, you can simply add this line to your JavaScript code:

$.cookie("PHPSESSID", null, {path: "/"});

If you are not using that plugin or jQuery at all, you have to use other / your own function or library for setting cookies with JavaScript. Internet is full of such examples. You may start here or here or on many other pages, blogs, tutorials etc.

You can either delete “PHPSESSID” cookie by setting its value to null or overwrite its value by pass an empty string instead of null value. Both solutions should work.

Make sure, that you are providing path information and you are setting path to root (/). If you omit that, browser will assume current path (which in most situation is not root) and either not delete any cookie (as PHPSESSID cookie with path different than root does not exists), in case you’re deleting cookie passing null value, or create a new cookie named PHPSESSID with current path (if you are overwriting cookie value by passing empty string). In both situations, user still will be logged-in after pressing F5, since main cookie (PHPSESSID with root path) will still be existing and set.

Non-default session name.

Above however, will work only, if you (or your system admin) hasn’t altered default session name for PHP which runs your application. That is: session.name parameter of php.ini file. For details refer to PHP Manual.

If you know, that default session name (PHPSESSID) has been altered and you know the altered name, simple change it in function you use for setting (actually deleting, as you are passing empty string) session cookie.

But if you don’t know altered cookie name, then the only solution that come to my mind is to change the way your JavaScript code will be sent to browser — from fixed, stored in script file (or HTML page) to auto-generated on server side.

Here is an example used in my Yii-based applications:

$myJavaScriptCode = 
'
var startTime = new Date();

function sessionTimeoutWatchdog()
{
    var timerDiv = document.getElementById("timer");
    var currentTime = new Date();
    var autologoffTime = '.$autologoffTime.';

    var differenceTime = autologoffTime - Math.round((currentTime - startTime) / 1000);
    var differenceDate = (differenceTime * 1000) - 3600000; //Fix for Date object...
    differenceDate = new Date(differenceDate);

    timerDiv.innerHTML = formatTime(differenceDate, "HH:MM:SS");

    if(differenceTime <= 0)
    {
            clearInterval(intervalID);
            $.cookie("'.(session_name()).'", null, {path: "/"});

            alert("Session has expired! You'll be reidrected to login screen...");

            window.location.href = "'.($this->createUrl('/account/logout')).'";
    }
}

intervalID = window.setInterval(sessionTimeoutWatchdog, 1000);
';

echo('<script type="text/javascript">'.$myJavaScriptCode.'</script>');

If you are using Yii Framework, you can replace:

$.cookie("'.(session_name()).'", null, {path: "/"});

with:

$.cookie("'.(Yii::app()->session->sessionName).'", null, {path: "/"});

and register script code instead of echoing it. I.e. remove echo() and replace it with:

Yii::app()->clientScript->registerScript('session-timeout-watchdog', $myJavaScriptCode, CClientScript::POS_HEAD);

Coclusion

I’m using a formatTime() function here. You may find here. This post is an extended version of this one.

Leave a Reply