Mvc3 Antiforgery token multi tabs
Asked Answered
C

2

10

we have a specific issue with the anti forgery token on the login page. If the user logs in with only one active window everything works great however if the user opens the login page in two different windows and logs in from window A (no issues will login), and the goes back to login from window B in this window the user will receive "A required anti-forgery token was not supplied or was invalid".

Is there any way around this other then to remove the anti forgery token from the view/controller action? We would prefer to have the token for additional security!

This is very similar to this question however this was asked for mvc2 MVC ValidateAntiForgeryToken multi-tabs problem

Cochin answered 26/3, 2012 at 23:4 Comment(1)
I've left you another answer - I should have answered my own question!Liquidation
C
27

This behaviour in MVC3 or MVC4 is as designed however it is very user-unfriendly as explained above, however in production this issue needs to be solved gracefully and application needs to handle this odd situation. The solution for this problem is to create a filter that is applied to the login post that will verify if the user is logged in and take them to the correct page otherwise they will remain on the login page.

Below is the code for the filter attribute

/// <summary>
/// Handle Antiforgery token exception and redirect to customer area if the user is Authenticated
/// </summary>
public class RedirectOnError : HandleErrorAttribute
{
    /// <summary>
    /// Override the on exception method and check if the user is authenticated and redirect the user 
    /// to the customer service index otherwise continue with the base implamentation
    /// </summary>
    /// <param name="filterContext">Current Exception Context of the request</param>
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.Exception is HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // Set response code back to normal
            filterContext.HttpContext.Response.StatusCode = 200;

            // Handle the exception
            filterContext.ExceptionHandled = true;

            UrlHelper urlH = new UrlHelper(filterContext.HttpContext.Request.RequestContext);

            // Create a new request context
            RequestContext rc = new RequestContext(filterContext.HttpContext, filterContext.RouteData);

            // Create a new return url
            string url = RouteTable.Routes.GetVirtualPath(rc, new RouteValueDictionary(new { Controller = "CustomerArea", action = "Index" })).VirtualPath;

            // Check if there is a request url
            if (filterContext.HttpContext.Request.Params["ReturnUrl"] != null && urlH.IsLocalUrl(filterContext.HttpContext.Request.Params["ReturnUrl"]))
            {
                url = filterContext.HttpContext.Request.Params["ReturnUrl"];
            }

            // Redirect the user back to the customer service index page
            filterContext.HttpContext.Response.Redirect(url, true);
        }
        else
        {
            // Continue to the base
            base.OnException(filterContext);
        }
    }
}

This is the example of usage

        [HttpPost]
        **[RedirectOnError]**
        [ValidateAntiForgeryToken]
        public ActionResult LogOn(LogOnViewModel model, UserSessionState session, string returnUrl)
        {
        .....
        }
Cochin answered 3/9, 2013 at 16:18 Comment(2)
I don't understand what happens if the user is not logged in... because remaining on the logging page might result in the exception again.Odont
In response to IlanS - code if (filterContext.Exception is HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated) will only apply the redirect if the user is logged in, otherwise the regular exception for a non authenticated user is thrown.Taneka
S
4

Once you log in, all previous tokens are invalid. That's how it's supposed to work. Naz gets close to the right answer except, the token in the cookie doesn’t store the username. Only the token in the form does. It is precisely because of this issue: if a user logs in, all existing form tokens should be invalidated, but invalidating the cookie itself would be too problematic and user-unfriendly.

Spider answered 26/3, 2012 at 23:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.