Monday, May 17, 2010

How to build login session timeout prompt message using jQuery

ASP.Net forms authentication session renew its authentication ticket only when the total escape time exceeds the half of the configured timeout. Say for example if you have 20 minutes configured in the web.config.
  1. Login time : 2.00 pm – Authentication ticket created (Expire on 2.20 pm)
  2. Do a postback: 2.05 pm. Before 10 minutes, which is a half of the configured timeout – Authentication ticket will not get renewed (Expire on 2. 20 pm)
  3. Leave browser – no postbacks
  4. Do a postback: 2.12 pm. After 10 minutes, which is a half of the configured timeout – Authentication ticket will get renewed (Expire on 2.32 pm)
If you need to have a time out message in your web page, we have to use a java script function with a counter. When counter comes to a certain point, say 2 minutes before the actual forms time out show the timeout message. However according to above explanation there is no constant timeout value for the first half of the timeout. Therefore we have to calculate the timeout and pass it to the java script function on each postback.

Example:





Test page inherit from the page base:

public class PageBase : Page
{
    private string startUpStript = @"
        var timeout = ({0} * 60) - 10;
        var timeEscaped = 0;
        var timerTicks = 0;
        var showBefore = 30
        function CountDown() {{
            if (timeEscaped < timeout - showBefore) {{
                setTimeout(CountDown, 1000);
                timeEscaped++;
            }}
            else
                ShowTimer();
        }}
        function ShowTimer() {{
            $("".LoginTimeout"").fadeIn();
            DisplayTime();
        }}
        function DisplayTime() {{
            if (timerTicks < showBefore) {{
                $("".LoginTimeout .TimeoutMessage .Timeout"").text(showBefore - timerTicks);
                timerTicks++;
                setTimeout(DisplayTime, 1000);
            }}
            else ShowTimedOutMsg();
        }}
        function ShowTimedOutMsg() {{
            $("".LoginTimeout .TimeoutMessage"").fadeOut();
            $("".LoginTimeout .LoggedOutMessage"").fadeIn();
        }}
        $(document).ready(function () {{
            CountDown()
        }});
    ";
    public LoginTimeout LoginTimeout
    {
        get { return (LoginTimeout)Session["LoginTimeout"]; }
        set { Session["LoginTimeout"] = value; }
    }
    public override void ProcessRequest(HttpContext context)
    {
        base.ProcessRequest(context);
        if (context.User != null && context.User.Identity.IsAuthenticated)
        {
            FormsIdentity identity = this.User.Identity as FormsIdentity;
            FormsAuthenticationTicket ticket = identity.Ticket;
            if (this.LoginTimeout == null || this.LoginTimeout.IssuedTime != ticket.IssueDate)
            {
                this.LoginTimeout = new LoginTimeout()
                {
                    IssuedTime = ticket.IssueDate,
                    TimeOut = FormsAuthentication.Timeout
                };
            }
            else
            {
                TimeSpan adjustment = DateTime.Now - this.LoginTimeout.IssuedTime;
                this.LoginTimeout.TimeOut = FormsAuthentication.Timeout - adjustment;
            }
        }
    }
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        if (this.LoginTimeout != null)
            this.Page.ClientScript.RegisterClientScriptBlock(
                this.GetType(),
                this.GetType().Name,
                string.Format(this.startUpStript, this.LoginTimeout.TimeOut.Minutes),
                true);
    }
 
}
public class LoginTimeout
{
    public DateTime IssuedTime { getset; }
    public TimeSpan TimeOut { getset; }
}

Test page markup:

<%@ Page Language="C#" AutoEventWireup="true"
     CodeBehind="Test.aspx.cs" Inherits="ActiveTest.Test" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Test Page</title>
    <style type="text/css">
        body { font-family:Tahomafont-size:11px; }
        p { padding:0margin:0; }
        .LoginTimeoutdisplay:none; 
                       padding:10px; 
                       background-color:#ffbd8c; 
                       height:15px; 
                       border:dotted 1px #f57313; 
                       text-align:center; 
                       width:300px; }
        .LoginTimeout .LoggedOutMessage,
        .LoginTimeout .TimeoutMessage { position:absolute; }
        .LoginTimeout .LoggedOutMessage { display:none; }
    </style>
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript" language="javascript"></script>
</head>
<body>
    Test Page
    <form method="get" action="Page2.html">
        <div class="LoginTimeout">
            <div class="TimeoutMessage">
                <p>Your login session will timeout in <strong>
                <span class="Timeout"></span></strong> seconds</p></div>
            <div class="LoggedOutMessage">
                <p>Your login sesson has timed out. You need to <a href="Login.aspx">
                login again</a></p></div>
        </div>
    </form>
</body>
</html>

Test page code behind:

namespace ActiveTest
{
    public partial class Test : PageBase
    {
 
    }
} 

Reference: Understanding the Forms Authentication Ticket and Cookie

2 comments:

Anonymous said...

Hi,

would this work if the Forms Auth Ticket is renewed on Callbacks (sliding expiration = true)?

Charith Shyam Gunasekara said...

Yes this works with Sliding Expiration mode

Azure Storage Account Types

Defferent Types of Blobs Block blobs store text and binary data. Block blobs are made up of blocks of data that can be managed individually...