Handling Session Timeout without Using Cookies

Printer-friendly version

Recently I’ve been working on the early stages of development for a website. While testing, the session state timeout was beginning to be quite a pain. Sure I can extend it, but if I walk away from my computer long enough for a timeout, I come back expecting to be able to use the site and am unpleasantly surprised when I realize my session has been lost. I needed to come up with a more graceful way to handle this situation.

My first decision was – why not just keep the session open indefinitely?  I’ll refresh the session every few minutes; this way if the user is logged in, they could walk away for as long as they want, come back, and be able to use the site as expected. If the browser is closed, the session will be unable to refresh and the timeout will take care of ending the session. To implement, I followed this example by Malcom Sheridon.

This method works, however, I just couldn’t get past the security hole that will exist if the session is constantly open. What if the user is on a public computer and leaves the browser open? Anyone could sit down at that computer and have complete access to the user’s account. This method wasn’t going to cut it; I had to end the session somehow. This is when I decided that a session timeout warning (popup) was going to be needed.

The alert would be needed on all pages, so I incorporated it into a user control on my master page. Here is what the front end looks like, where “divTimeoutPopup” is the semi-transparent background, and “innerPopup” is the alert itself:

[code language="html"] 
<div id="divTimeoutPopup"></div> 
<div id="innerPopup"> 
    <div id="divTimeLeft"></div> 
    <br /> 
    <asp:Button ID="btnOK" runat="server" Text="OK" OnClick="btnOK_Click" /> 
    <asp:Button ID="btnLogout" runat="server" Text="Logout" OnClick="btnLogout_Click" /> 
</div> 
[/code] 

On Page_Load on my master page, I had the following:

[code language="csharp"] 
//  we only want the popup to show if the user is logged in 
If (UserLoggedIn) 
{ 
//  this line is taken from the blog mentioned above 
//  when a postback occurs the session will be refreshed 
//  but not if the user clicks the back/forward buttons 
//  in their browser, so we will call this just to make 
//  sure the session gets refreshed 
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "keepAlive", "KeepSessionAlive('" + ResolveUrl("~/KeepSessionAlive.ashx") + "');", true); 
 
//  this line will show the timeout message after a 
//  given time (I have it set to 5 seconds for testing 
//  purposes 
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "initiateTimeout", "setTimeout(function(){showTimeoutMessage('" + ResolveUrl("~/Logout.aspx?msg=sessiontimeout") + "')}, 5000);", true); 
} 
[/code] 

I should note that I use subdirectories in my site so I use ResolveUrl to help with the issue of absolute/relative paths within a master page. If you don't use subdirectories you don't need to pass in the URLs that you need and can put them directly into your javascript. The first function KeepSessionAlive is in my master page (or linked .js file) and looks like this:

[code language="javascript"] 
function KeepSessionAlive(pageURL) { 
    $.post(pageURL, null, function () { }); 
} 
[/code] 

If you didn't get a chance to look at the blog post mentioned above, the code for KeepSessionAlive.ashx is shown below. Basically all this does is set a session value, which refreshes the current session and keeps it active.

[code language="csharp"] 
<%@ WebHandler Language="C#" Class="KeepSessionAlive" %> 
 
using System; 
using System.Web; 
using System.Web.SessionState; 
 
public class KeepSessionAlive : IHttpHandler, IRequiresSessionState 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
        context.Session["KeepSessionAlive"] = DateTime.Now; 
    } 
 
    public bool IsReusable 
    { 
        get 
        { 
            return false; 
        } 
    } 
} 
[/code] 

Next showTimeoutMessage is the code that actually displays the popup, this I have in my user control

[code language="javascript"] 
function showTimeoutMessage(logoutURL) { 
//  show the popup 
        $('#divTimeoutPopup').css('display', 'block'); 
        $('#innerPopup').css('display', 'block'); 
        $('#divTimeoutPopup').css('opacity', '0.5'); 
 
//  second value at which our countdown begins 
        var secondsLeft = 3; 
        UpdateTime(); 
        setInterval(UpdateTime, 1000); //every second update the seconds left 
 
        function UpdateTime() { 
            if (secondsLeft > 0) { 
                $('#divTimeLeft').text('You have ' + secondsLeft + ' seconds before your session expires! Click OK to continue your session.'); 
                secondsLeft--; 
            } else if (secondsLeft == 0) { 
                window.location.href = logoutURL; // if time has run out, redirect the user to the logout page 
            } 
             
        } 
    } 
[/code] 

OK, so now we have everything in place to actually display the popup, now all we need to do is write the code for the buttons in the popup. Here is the code behind for my user control:

[code language="csharp"] 
protected void btnLogout_Click(object sender, EventArgs e) 
    { 
        Response.Redirect("~/Logout.aspx"); 
    } 
 
    protected void btnOK_Click(object sender, EventArgs e) 
    { 
        ScriptManager.RegisterStartupScript(Page, Page.GetType(), "refreshSession", "RefreshSession('" + ResolveUrl("~/KeepSessionAlive.ashx") + "', '" + ResolveUrl("~/Logout.aspx?msg=sessiontimeout") + "');", true); 
    } 
[/code] 

As you can see the logout button simply redirects the user to the logout page. The OK button will refresh the user's session. Here is the javascript for RefreshSession() which I have located in my user control.

[code language="javascript"] 
function RefreshSession(pageURL, logoutURL) { 
// refresh the session 
        $.post(pageURL, null, function () { }); 
 
//  hide the popup divs 
        $('#divTimeoutPopup').css('display', 'none'); 
        $('#innerPopup').css('display', 'none'); 
 
//  call this again so that the popup can display again if needed 
        setTimeout(function () { showTimeoutMessage(logoutURL) }, 5000) 
    } 
[/code] 

It may seem like a lot, but it is actually pretty simple. Keep in mind I have my session set to timeout after 1 minute and my popup to display after 5 seconds - this is merely for testing purposes as it would be a nuisance to have a session popup so often! I suggest keeping the popup display time as close to your session timeout as possible to minimize unnecessary posts. You will have to decide on a value for your session timeout (in web.config) - this is important to know because this will be the minimum amount of time it will take to end the session if the browser has been closed.

About the Author:

TopLine Strategies delivers the complete integration and development of sales, marketing and customer service technologies that enable corporate clientele to improve revenue streams and strengthen customer interactions. Our project management and consulting is designed to achieve timely delivery, 100 percent user adoption of the technologies we implement and deliver measurable returns on investments for our clients.

Comments (0)

Related Blogs

TheReact Native Open Source roadmap was announced in Q4 2018 after they decided to invest more in the React Native open source community.

October is not just about pumpkins, fall foliage, and cooler temps anymore. October 2018 also means the exciting introduction of Microsoft Dynamics 365 for Customer Engagement.

Back in 2016, Microsoft introduced its intentions to refresh its CRM and ERP strategy with Dynamics 365. At the heart of its services was the Common Data Model (CDM).