-2

In my MVC5 application, implemented anti-forgery token. When user launch and login, it works. In case if user click the browser back after login and resubmit the with different credentials, it show

The provided anti-forgery token was meant for user "xxxx", but the current user is "yyyy"

In the login controller, I have tried something like

public ActionResult Index()
{
    if (User != null && (User.Identity.IsAuthenticated || User.Identity.Name != ""))
    {
        FormsAuthentication.SignOut();
        Session.Abandon();
        return RedirectToAction("Index");
    }
    return View();
}

But the system doesn't fire the action in this case.

Krishna Sarma
  • 1,852
  • 2
  • 29
  • 52

2 Answers2

3

This is common when we have anti forgery tokens.

This is happening because the anti-forgery token embeds the username of the user as part of the encrypted token for better validation. When you first call the @Html.AntiForgeryToken() the user is not logged in so the token will have an empty string for the username, after the user logs in, if you do not replace the anti-forgery token it will not pass validation because the initial token was for anonymous user and now we have an authenticated user with a known username.

You have a few options to solve this problem:

1- Just this time let your application do a full POST and when the page reloads it will have an anti-forgery token with the updated username embedded.

2- Have a partial view with just @Html.AntiForgeryToken() and right after logging in, do another AJAX request and replace your existing anti-forgery token with the response of the request.

3- Just disable the identity check the anti-forgery validation performs. Add the following to your Application_Start method: AntiForgeryConfig.SuppressIdentityHeuristicChecks = true.

The validation code that runs against an AntiForgeryToken also checks your logged in user credentials haven’t changed – these are also encrypted in the cookie. This means that if you logged in or out in a popup or another browser tab, your form submission will fail with the following exception:

System.Web.Mvc.HttpAntiForgeryException (0x80004005):
The provided anti-forgery token was meant for user "xxxx", but the current user is "yyyy".

You can turn this off by putting AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start method inside Global.asax file.

When a AntiForgeryToken doesn’t validate your website will throw an Exception of type System.Web.Mvc.HttpAntiForgeryException. You can make this a little easier by at least giving the user a more informative page targeted at these exceptions by catching the HttpAntiForgeryException.

private void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

    if (ex is HttpAntiForgeryException)
    {
        Response.Clear();
        Server.ClearError(); //make sure you log the exception first
        Response.Redirect("/error/antiforgery", true);
    }
}

Here is the SO thread for the similar problem.

additional reference.

staticvoidmain
  • 793
  • 6
  • 14
  • `AntiForgeryConfig.SuppressIdentityHeuristicChecks = true` does not work for me :( Using Asp.NET MVC 5... I've been searching around for an MVC 5 solution and still havent found one. – Jimbo Oct 26 '18 at 08:29
0

Decorate your Login GET method with

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult Login(...)

to prevent the page being cached. This will force a new token to be created without the previously logged in users username.