Search code examples
asp.net-mvc-3csrf

ASP.NET MVC3 - Anti-CSRF and Session timeout


I am implementing Anti-Forgery framework as described here:

http://weblogs.asp.net/srkirkland/archive/2010/04/14/guarding-against-csrf-attacks-in-asp-net-mvc2.aspx

Plus, to minimize the coding effort, I did the token insertion part at client side handling form.onsumit and ajaxsend events. Everything works fine – until the session expires.

In my application, I display a popup when the user session gets timed out where the user can re-login and continue without refreshing the current page so that the work-in-progress will be safe. But this doesn't go well with the Anti-CSRF logic. When the user tries to re-login after a timed-out session, this throws a CSRF exception as the cookie (__RequestVerificationToken_Lw__) is already expired and all the future POSTs will be invalid until next page refresh.

Is there any way to set the cookie end time to a future date rather than 'session'? I tried to edit Response.Cookie but that made the cookie invalid.

Any help would be appreciated. Thanks


Solution

  • At the time of user session out (when displaying a popup) is it possible for you to set the httpcookie with expiry in server side.

    I have extracted some code from the microsofts antiforgery token implementation.

    internal static string GetAntiForgeryTokenName(string appPath)
            {
                if (string.IsNullOrEmpty(appPath))
                {
                    return "__RequestVerificationToken";
                }
                return "__RequestVerificationToken_" + Base64EncodeForCookieName(appPath);
            }
    
        private static string Base64EncodeForCookieName(string s)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            string text = Convert.ToBase64String(bytes);
            return text.Replace('+', '.').Replace('/', '-').Replace('=', '_');
        }
    

    Below code which set the cookie in server side.

    string antiForgeryTokenName = GetAntiForgeryTokenName(HttpContext.Request.ApplicationPath);
                HttpCookie httpCookie = HttpContext.Request.Cookies[antiForgeryTokenName];
    
                HttpCookie httpCookie2 = new HttpCookie(antiForgeryTokenName, httpCookie.Value)
                {
                    HttpOnly = true
                    //// your domain Domain = , 
                    //// path Path = , 
                    //// set path Expires = 
                };
    
                HttpContext.Response.Cookies.Set(httpCookie2);
    

    Please note that I haven't tested this code, just give a try if you dont have any other options.