How to Set Up Automatic Session Timeout with Ajax
See Ajax: Tips and Tricks for similar articles.If a user is idle for a certain amount of time, it is often a good idea to set up an automatic session timeout with Ajax to force a logout, especially if there might be sensitive data on the screen. This is normally handled on the server side; however, if we want to hide the data on the screen and alert the user that the session has ended, we'll need to handle the session on the client as well. One way to handle this is described below:
- When the user logs in, create a JavaScript timer with the
window.setTimeout()
method. The timer will call a function that ends the session after n minutes. - Whenever there is user activity, the timer must be restarted.
- When the user explicitly logs out (e.g., clicks on a logout button), the timer must be killed.
For these examples to work, more files are required than are available in this how to. To see these examples in action, take the Ajax training course.
In this example, we'll look at a simple login form. The user logs in and is provided with a log out button. When the session times out, the page goes blank and an alert appears informing the user that the session has timed out.

After the user clicks on the OK button, the login form reappears. Let's look at the code. There are quite a few steps involved in setting up an automatic session timeout with Ajax, as shown below.
- First, we start with the code sample:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Authentication</title> <link href="Presidents.css" type="text/css" rel="stylesheet"> <link href="Login.css" type="text/css" rel="stylesheet"> <script type="text/javascript" src="lib.js"></script> <script type="text/javascript" src="inline-editing.js"></script> <script type="text/javascript"> var presConfig = { userName: null, autoLogoutTimer: null } function startApp() { var loggedInDiv = document.getElementById("LoggedInDiv"); var logOutDiv = document.getElementById("LogoutDiv"); loggedInDiv.innerHTML = "Logged in as " + presConfig.userName; loggedInDiv.style.display = "block"; logOutDiv.style.display = "block"; showPresidents(); startAutoLogoutTimer(); observeEvent(document.body, "click", startAutoLogoutTimer); } function endApp() { var loggedInDiv = document.getElementById("LoggedInDiv"); var logOutDiv = document.getElementById("LogoutDiv"); clearTimeout(presConfig.autoLogoutTimer); presConfig.userName = null; loggedInDiv.innerHTML = ""; loggedInDiv.style.display = "none"; logOutDiv.style.display = "none"; loginForm(); unObserveEvent(document.body, "click", startAutoLogoutTimer); } function showPresidents() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "Controller?req=Table", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { var output = document.getElementById("Output"); output.innerHTML = xmlhttp.responseText; enableEditing(); } } function loginForm() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "Controller?req=LoginForm", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { var output = document.getElementById("Output"); var loginForm; output.innerHTML = xmlhttp.responseText; loginForm = document.getElementById("LoginForm"); loginForm.onsubmit = function() { login(loginForm.Username.value, loginForm.Password.value); return false; } } } function login(un, pw) { var params = "username=" + un + "&password=" + pw; var xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", "Controller?req=Login", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); xmlhttp.send(params); function results(xmlhttp) { if (xmlhttp.responseText.indexOf("failed") == -1) { presConfig.userName = xmlhttp.responseText; startApp(); } else { var badLogin = document.getElementById("BadLogin"); var userName = document.getElementById("Username"); badLogin.style.display = "block"; userName.select(); userName.className = "Highlighted"; setTimeout(function() { document.getElementById('BadLogin').style.display = 'none'; }, 5000); } } } function startAutoLogoutTimer() { var sessionTime = 15 * 1000; //15 seconds clearTimeout(presConfig.autoLogoutTimer); presConfig.autoLogoutTimer = setTimeout(function() { logout(true); }, sessionTime); } function logout(auto) { var xmlhttp = new XMLHttpRequest(); document.getElementById("Output").innerHTML = ""; xmlhttp.open("GET", "Controller?req=Logout", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { endApp(); if (auto) { alert("You have been logged out due to inactivity."); } } } function checkLogin() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "Controller?req=LoggedIn", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { if (xmlhttp.responseText.indexOf("failed") == -1) { presConfig.userName = xmlhttp.responseText; startApp(); } else { loginForm(); } } } observeEvent(window, "load", function() { var btnLogout = document.getElementById("logout"); observeEvent(btnLogout, "click", function() { logout(false); }); checkLogin(); }); </script> </head> <body> <div id="LogoutDiv"> <button id="logout">Logout</button> </div> <div id="LoggedInDiv"></div> <div id="Output">One moment please...</div> </body> </html>
- Now let's dissect the code so you can see how the automatic session timeout is created. This page contains the basic HTML elements that will hold data returned from the server:
The "Output" div will hold the login form or the table data, depending on whether the user is logged in. This page also controls the flow of the application:<div id="LogoutDiv"> <button id="logout">Logout</button> </div> <div id="LoggedInDiv"></div> <div id="Output">One moment please...</div>
- When the page loads, the
checkLogin()
function is called, which looks like this:
It makes an Ajax request to Controller, which handles the assignment of tasks based on thefunction checkLogin() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "Controller?req=LoggedIn", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { if (xmlhttp.responseText.indexOf("failed") == -1) { presConfig.userName = xmlhttp.responseText; startApp(); } else { loginForm(); } } }
req
parameter. In this case, the server-side code checks to see if the user is logged in: if so, it returns the user's name; if not, it returns the text "failed" if s/he is not logged in. Theresults()
callback function then callsstartApp()
(if the user is logged in) to start the application or loginForm() (if the user is NOT logged in) to show the login form. - Let's first see what happens when the user is NOT logged in:
Thefunction loginForm() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "Controller?req=LoginForm", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { var output = document.getElementById("Output"); var loginForm; output.innerHTML = xmlhttp.responseText; loginForm = document.getElementById("LoginForm"); loginForm.onsubmit = function() { login(loginForm.Username.value, loginForm.Password.value); return false; } } }
loginForm()
function uses Ajax to get an HTML login form and then, in theresults()
callback function displays the form and attaches thelogin()
function to itssubmit
event. - When the user logs in, the
login()
function is called:function login(un, pw) { var params = "username=" + un + "&password=" + pw; var xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", "Controller?req=Login", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); xmlhttp.send(params); function results(xmlhttp) { if (xmlhttp.responseText.indexOf("failed") == -1) { presConfig.userName = xmlhttp.responseText; startApp(); } else { var badLogin = document.getElementById("BadLogin"); var userName = document.getElementById("Username"); badLogin.style.display = "block"; userName.select(); userName.className = "Highlighted"; setTimeout(function() { document.getElementById('BadLogin').style.display = 'none'; }, 5000); } } }
- The
startApp()
function does the following:- Shows the logged-in message and the Logout button.
- Calls
showPresidents()
, which gets the editable Presidents table. - Calls
startAutoLogoutTimer()
, which starts the inactivity timer. This function is recalled every time the user clicks the mouse. It is shown below:function startAutoLogoutTimer() { var sessionTime = 15 * 1000; //15 seconds clearTimeout(presConfig.autoLogoutTimer); presConfig.autoLogoutTimer = setTimeout(function() { logout(true); }, sessionTime); }
startAutoLogoutTimer()
function simply sets a timer to calllogout()
after 15 seconds and passing in true to indicate that it is an auto logout vs. a user-initiated logout. The function is recalled (and the timer restarted) each time the user clicks the mouse. We set the timer at 15 seconds so that you wouldn't have to wait too long to see it work. Normally, it would be much longer. - The
logout()
function is shown below:
As we don't need a response from the server to log the user out, we use the "HEAD" method to send the request. The rest of the function sets the page back as it was when it first loaded.function logout(auto) { var xmlhttp = new XMLHttpRequest(); document.getElementById("Output").innerHTML = ""; xmlhttp.open("GET", "Controller?req=Logout", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { results(xmlhttp); } } xmlhttp.send(null); function results(xmlhttp) { endApp(); if (auto) { alert("You have been logged out due to inactivity."); } } } }
Related Articles
- How to Make a Cross-origin Ajax Request
- How to Create a Login Form with Ajax
- How to Set Up Automatic Session Timeout with Ajax (this article)
- How to Use the Callback Function in Ajax
- How to Develop a Web Application with Ajax
- How to Make GET, POST, and HEAD Requests Using Ajax
- How to Use the jQuery ajax() Method
- How to Create a Lookup Form with Ajax
- How to Create a Slideshow with Ajax
- How to Handle the Response from the Server in Ajax
- How to Set Up for Ajax Training on Windows
- Inline Editing Using Ajax
- How to Create a Navigable Table with Ajax