Applications

Session Sliding and Expiration Handling

I was recently developing an MVC cloud service application that uses Windows Identity Foundation to issue security tokens. The app stores content and provides an interface for users to take courses on corporate practices. Certain users have permission to manage course content which gives them access to a fairly time consuming create/edit form.

The problem here is that when the session security token expires the user would lose all their progress because there is a passive redirect to the STS (secure token service). Luckily I found an article describing how to check the token after each HTTP request and renew it if it has reached its half-life (http://brockallen.com/2013/02/17/sliding-sessions-in-wif-with-the-session-authentication-module-sam-and-thinktecture-identitymodel/).
The sliding security token functionality solves half of the problem. The user could still lose their progress on the form if they don’t post back before the session token expires. To remedy this, I created a warning dialog that will extend the session if they click the button, or it’ll save a draft of the course if they don’t.

Sliding the session token

By hooking into the ‘session security token received’ event in the session authentication module (global.asax), you can check if the session token has passed its half-life and renew its expiration date. This event is fired at each HTTP request.
protected void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
        {
            SessionAuthenticationModule sam = FederatedAuthentication.SessionAuthenticationModule;
 
            var token = e.SessionToken;
            var duration = token.ValidTo.Subtract(token.ValidFrom);
            if (duration <= TimeSpan.Zero) return;
 
            var diff = token.ValidTo.Add(sam.FederationConfiguration.IdentityConfiguration.MaxClockSkew).Subtract(DateTime.UtcNow);
            if (diff <= TimeSpan.Zero) return;
 
            var halfWay = duration.TotalMinutes / 2;
            var timeLeft = diff.TotalMinutes;
            if (timeLeft <= halfWay)
            {
                e.ReissueCookie = true;
                e.SessionToken =
                    new SessionSecurityToken(
                        token.ClaimsPrincipal,
                        token.Context,
                        DateTime.UtcNow,
                        DateTime.UtcNow.Add(duration))
                    {
                        IsPersistent = token.IsPersistent,
                        IsReferenceMode = token.IsReferenceMode
                    };
            }
        }

Auto-save form before token expiration

I added a partial razor view that will initialize the dialog two minutes before the session expires, then the user has two minutes to extend the session or the course is saved as a draft. I added this partial view to my form in a div with id ‘sessionHandler’.
@{
    var beforeEndSession = 60000 * (Session.Timeout – 2);
}
<script>
    var saveDraft = function () {
        $(‘input[name="autoSave"]’).val("true");
        $(‘input[name="Draft"]’).click();
    };
   
    var myWarning = function () {
        var autoSave = window.setTimeout(saveDraft, 120000);
        $(‘#extend-session’).dialog({
            dialogClass: "session-warning",
            width: "auto",
            resizable: false,
            modal: true
        });
        $(‘#extend-session input’).click(function() {
            $(‘#extend-session’).dialog(‘destroy’);
            window.clearTimeout(autoSave);
        });
    };
   
    window.setTimeout(myWarning, @beforeEndSession);
 
</script>
<div id="extend-session" >
    <span>Your session is about to expire</span>
    @using (Ajax.BeginForm("ContinueSession", "Courses", null, new AjaxOptions {UpdateTargetId = "sessionHandler", InsertionMode = InsertionMode.Replace}))
    {
        <input type="submit" value="Extend Session"/>
    }
</div>
If the ‘Extend Session’ button isn’t clicked after two minutes (120,000 milliseconds), the ‘saveDraft’ function is called which sets the auto-save flag to true and submits the form. The auto-save flag triggers logic in the controller to bypass validation and notify the user. If the ‘Extend Session’ button is clicked, the auto-save timer is cleared and an Ajax call returns the same partial, refreshing the session.
public ActionResult ContinueSession(bool isEditTimeout)
{
return PartialView("_EditTimeout");
}
 

One Response

  1. Joris August 4, 2015

Leave a Reply