ASP.NET MVC - ValidateAntiForgeryToken expiring
Asked Answered
W

1

18

In a web page we provide a hyperlink (GET) that the User may click on to authenticate:

@Html.ActionLink("Please Login", "MyMethod", "MyController")

This maps to the following controller method which returns a View:

    [RequireHttps]
    public ActionResult MyMethod()
    {
        return this.View(new MyModel());
    }

This View contains the Form in which the User supplies their credentials; the Form contains the required AntiForgeryToken.

When the User submits the form, the following Controller method is called:

    [HttpPost]
    [RequireHttps]
    [ValidateAntiForgeryToken]
    public ActionResult MyMethod(MyModel model)
    {
        // my logic
    }

This works perfectly well, most of the time...

However, if the User leaves their browser open for a "significant" period of time and then performs the following steps in quick succession:

  1. Clicks on the hyperlink (GET) to load the log-in form
  2. Completes the form and submits

They get an exception informing them that the Anti-Forgery token was either not provided or was invalid.

I don't understand why this is the case: the View (containing the form) is created after the browser was dormant and so the anti-forgery tokens should all be "fresh". However, something is evidently wrong with this design, but I'm not sure how best to rectify it.

Thanks in advance if you have any suggestions.

Griff

Won answered 1/10, 2012 at 18:32 Comment(3)
I just want to mention that my app has experienced this problem for a few years and I would love to have a solution. I tried all of the standard machine key fixes.Idiocy
Roll up those sleeves and dive into the source. I'll man the pump.Steele
There is an article which details the validation steps for the token. One step is to validate against the Context's user - not sure if that might have gone out of step. Either way, the solution remains unclear.Won
O
19

I'm dealing with this same problem and while I understand the issue, I'm not sure yet of the best resolution.

The Anti-ForgeryToken process places an input value in the form with a second value stored in a cookie RequestVerificationToken. Both of these are submitted to the server and if they don't match the error is thrown.

The RequestVerficationToken cookie has an expiration value set to be Session. So when the user leaves the browser open on the page for a long time and then submits, the cookie's time stamp is compared to the session timeout value on the server — a default of 20 minutes or so — and having been exceeded, it is removed and thus token validation fails.

Possible solutions, all of which have potential issues;

  1. Put a javascript timer on the page and refresh at some value less than your session timeout.
  2. Catch the System.Web.Mvc.HttpAntiForgeryException on the server — and redirect to the same page.
  3. Increase your session timeout
  4. Change the expiration on the anti-forgery token
Overdose answered 10/4, 2013 at 18:34 Comment(2)
Note, as I understand it, the machine key is used to validate the Anti-ForgeryToken on the server and is necessary for usage in a webfarm (and setting a static machine key might resolve an error condition caused by a restart of the worker process on the server), however it will not resolve the cookie expiration issue.Overdose
As you said the cookie expiration is tied to the Session so solution 3 should also result in solution 4. Unless you manually override how the cookie is generated somehow. I have tried solution 1 in the past and it's not always totally reliable so a combination of 3 (if possible) and 2 seem like the best options.Intertexture

© 2022 - 2024 — McMap. All rights reserved.