Login request validation token issue

我怕爱的太早我们不能终老 提交于 2019-11-29 19:15:37

I've just tested this pattern on ASafaWeb with the same result (it uses the same default implementation). Here's what I believe is happening

  1. Both login forms load with the same __RequestVerificationToken cookie (it's just the same one set in the same DOM) and the same __RequestVerificationToken hidden field. These tokens are keyed to an anonymous user.
  2. Login form A posts with the above tokens, validates them then returns an auth cookie which is now in the browser DOM
  3. Login form B posts also with the above tokens but now it's also posting with the auth cookie set from login form A as well.

The problem is that the token isn't validating in step 3 because it's keyed to an anonymous user but it's being passed in the request by an authenticated user. This is why you're seeing the error: The provided anti-forgery token was meant for user "", but the current user is "admin"

You're only having this issue because form B loaded before form A posted therefore form B is expecting to be posted by an anonymous user.

Is it an issue to remove it from a form which by definition will be used by unauthenticated users?

The predominant underlying risk that anti-forgery tokens protect against is CSRF which usually takes advantage of authenticated users due to the fact that any requests their browser can be tricked into issuing will be automatically accompanied by an auth cookie hence the action will be performed on their behalf. This risk doesn't exist on the login form because usually the user isn't authenticated and the worst CSRF case here is that a login is forged and then fails; you're not exactly transferring money on the user's behalf!

There are other advantages to the anti-forgery token though: for example it prevents brute force attacks actually executing the method and hitting the DB. You need to decide if you're less worried about this and more worried about the scenario you're encountering in your question. Either that or you need to drop down into the request pipeline somewhere and take action if an auth cookie is already present in the request before the anti-forgery validation occurs.

Frankly though, I'm not sure I see the problem; to reproduce this issue the user has to have multiple login forms open at the same time and then try logging into each in succession - is this really going to happen enough to worry about? And when it does happen, does it really matter that the second login returns a custom error page (which of course you'd do in production)? IMHO, leave the default behaviour.

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 "", but the current user is "SomeOne".

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);
  }
}

Okay, please correct me if my assumption is incorrect.

When this exception gets thrown, you would prefer to let the user continue on while also maybe displaying a relevant message/warning? Because when this exception gets thrown, we can already know if the current user is authenticated--we have access to the request.

So, why wouldn't this be acceptable?

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
...
}

/// <summary>
/// Handle HttpAntiForgeryException and redirect if user is already authenticated
/// </summary>
/// <param name="filterContext"></param>
/// <remarks>
/// See: http://stackoverflow.com/questions/19096723/login-request-validation-token-issue
/// </remarks>
protected override void OnException(ExceptionContext filterContext)
{
    base.OnException(filterContext);

    var action = filterContext.RequestContext.RouteData.Values["action"] as string;
    var controller = filterContext.RequestContext.RouteData.Values["controller"] as string;

    if ((filterContext.Exception is HttpAntiForgeryException) &&
        action == "Login" &&
        controller == "MyController" &&
        filterContext.RequestContext.HttpContext.User != null &&
        filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
    {
        LogManager.GetCurrentClassLogger().Warn(
            "Handled AntiForgery exception because user is already Authenticated: " +
                filterContext.Exception.Message, filterContext.Exception);

        filterContext.ExceptionHandled = true;

        // redirect/show error/whatever?
        filterContext.Result = new RedirectResult("/warning");
    }
}

Am I missing something obvious here? I'll remove this answer if it has some implication I'm not seeing.

I had the same issue, I solved it by adding machineKey to system.web>

<machineKey validationKey="your machine key numbers" 
decryptionKey="Your description key nuumbers" validation="SHA1" decryption="AES" />

Here's a site that generate unique Machnie Keys http://www.developerfusion.com/tools/generatemachinekey/

Works great, I understand that Anti Forgery may not be needed in a Login page, but if someone is determined to hack you site, it comforting to know that [ValidateAntiForgeryToken] is there to thwart them off.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!