Session expiration - SSO
Warning a User About Session Expiry
In a default configuration, when a session times out at the SP (application side), the user is redirected to Ubisecure SSO on the next attempt to access a protected resource. If the SSO session has also expired, the user will be prompted to login again. Ubisecure SSO does not maintain a history of recently used sessions – even if the server session has only recently expired, no specific instructions can be given to the user at the Ubisecure SSO. At the Ubisecure SSO it is not possible to determine if the SSO session has just expired or if the user is accessing the site for the first time.
The applications being integrated have the best knowledge of the user's individual behavior within an application and the desired security requirements of individual applications. All major application servers and programming frameworks provide session management facilities for this purpose. These session management techniques work in addition to the Ubisecure SSO session.
There are many different ways the applications can deal with the situation of user session expiring. The application could notify the user a bit before the application session is about to expire. It could also just keep the user application session from timing out by making automatic requests to the application at certain time intervals. Also the SSO session can be kept from expiring by using the techniques mentioned below in Preventing SSO and Application Session Expiration. If the user chooses to confirm the session, call the Ubisecure SSO uas/refresh address and refresh also the application session timer. If the user chooses to logout, call the logout process using the technique supported by the Web Application or SAML SP in use.
Preventing SSO and Application Session Expiration
If it is desired that a session does not expire for a given application when the application is kept open, use meta-refresh settings to either reload the current page or JavaScript to query the uas/refresh address at regular intervals shorter than the server session length.
A call to the address https://www.example.com/uas/refresh
, or any resource under this path, will refresh any active Ubisecure SSO sessions. This call must be made from the user’s browser. This can be performed using a JavaScript timeout timer.
Here is an example of how to do the img
tag style refresh that refreshes the SSO session every 10 minutes:
<script type="text/javascript"> function sessionKeepAlive(imgName) { myImg = document.getElementById(imgName); if(myImg) myImg.src = myImg.src.replace(/\?.*$/, '?' + Math.random()); } window.setInterval("sessionKeepAlive('keepAliveIMG')", 600000); </script>
<img id="keepAliveIMG" width="1" height="1" src="https://www.example.com/uas/refresh/status.gif?"/>
Here is an example code on how to keep application session refreshed with a whole-page refresh every 10 minutes:
<meta http-equiv="refresh" content="600" />
The img
tag style refresh is recommended over the meta-refresh, because it does not reload the whole page and thus possibly lose some valuable data if the user was just filling out a form etc.
The image loading technique can also be applied to refreshing the application session. What is needed is some handler code in the server to refresh the session and return a small transparent 1x1 image. Here is a code example showing how it could be done in a Java servlet container:
public class ImageServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // To refresh the session HttpSession session = request.getSession(false); ServletContext sc = getServletContext(); String filename = sc.getRealPath("images/empty.png"); String mimeType = sc.getMimeType(filename); if (mimeType == null) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } response.setContentType(mimeType); File file = new File(filename); response.setContentLength((int) file.length()); FileInputStream in = new FileInputStream(file); OutputStream out = response.getOutputStream(); byte[] buf = new byte[1024]; int count = 0; while ((count = in.read(buf)) >= 0) { out.write(buf, 0, count); } in.close(); out.close(); } }
Informing The User About Expiring Application Session
There are many different ways to notify users that their application session is about to expire. Here, we give 2 possible solutions.
Taking User to a "Session Expiration" Page Just Before Session Expiration
The idea here is to use JavaScript to check if the current page has been shown to user so long that the session is about to expire. When this happens, JavaScript code will load a session expiration page.
<script language="javascript" type="text/javascript" src="js/SessionExpiry.js"></script> <script type="text/javascript"> var callback = function() { // Take the user to another page just before session expiration. document.location = "expiry.jsp"; }; // The time in milliseconds for the moment before actual session expiry (29 minutes) var timeout = 1740000; initializeExpiryTracking(); // The polling interval should be much less than the session timeout // if users open multiple windows and all the windows are wanted to // react to the session expiry somehow. If this is not important (or // not preferred), just set the interval the same as the timeout. window.setInterval("checkSessionExpiry(timeout, callback)", 5000); </script>
/** * Initializes the session expiration tracking by marking the last * http request time in a cookie. */ function initializeExpiryTracking() { setCookie("lastRequestTime", new Date().getTime()); } /** * Checks if the time between now and last http request is bigger * than the session timeout and if so, executes the callback function. * * @param timeout Session timeout * @param callback a function that is called when session expiration * happens */ function checkSessionExpiry(timeout, callback) { lastRequestTimeString = getCookie("lastRequestTime"); lastRequestTime = parseInt(lastRequestTimeString); if(new Date().getTime() - lastRequestTime >= timeout || cookieAlreadyDeleted()) { deleteCookie("lastRequestTime"); callback(); } } function cookieAlreadyDeleted() { return isNaN(lastRequestTime); } /** * Returns a cookie value for the given cookie name. * * @param name */ function getCookie(name) { var nameMatch = name + "="; var cookieArray = document.cookie.split(';'); for(var i = 0; i < cookieArray.length; i++) { var c = cookieArray[i]; while(c.charAt(0) == ' ') c = c.substring(1, c.length); if(c.indexOf(nameMatch) == 0) return c.substring(nameMatch.length, c.length); } return null; } /** * Sets a cookie with the given name and value. Uses default expiration and "/" * as path. * * @param name * @param value */ function setCookie(name, value) { document.cookie = name + "=" + value + ";path=/"; } /** * Deletes a cookie with a given name from the "/" path. * * @param name */ function deleteCookie(name) { if(getCookie(name)) { document.cookie = name + "=" + ";path=/" + ";expires=Thu, 01-Jan-1970 00:00:01 GMT"; } } /** * Changes the image src attribute of the image that has the given Id. This basically * makes the browser to reload the image. * * @param imgName */ function sessionKeepAlive(imgName) { myImg = document.getElementById(imgName); if(myImg) myImg.src = myImg.src.replace(/\?.*$/, '?' + Math.random()); }
Showing a Notification Popup Just Before Session Is Expiring
The idea here is basically the same as in the previous technique of taking user to a session expiration page. We just change the callback code to ask user whether he wants to refresh the session or not.
<script language="javascript" type="text/javascript" src="js/SessionExpiry.js"></script> <script type="text/javascript"> var intervalId = 0; var callback = function() { // Here you can do whatever is wanted to be done just before session expiration. if(confirm("Your session is about to expire. Do you want to continue the session?")) { window.clearInterval(intervalId); sessionKeepAlive("keepAliveIMG"); initializeExpiryTracking(); intervalId = window.setInterval("checkSessionExpiry(timeout, callback)", 5000); } else { document.location = "expiry.jsp"; } }; // The time in milliseconds for the moment before actual session expiry var timeout = 50000; initializeExpiryTracking(); // The polling interval should be much less than the session timeout // if users open multiple windows and all the windows are wanted to // react to the session expiry somehow. If this is not important (or // not preferred), just set the interval the same as the timeout. intervalId = window.setInterval("checkSessionExpiry(timeout, callback)", 5000); </script>