title: MVC Anti-Forgery Token Validation - Random Error
body: <p>I have an MVC 3.0 App.  In production, we randomly receive an exception that says "A required anti-forgery token was not supplied or was invalid".  This doesn't happen to every user, so it's safe to say that the anti-forgery token process is setup right.  However it does happen to some users every time they sign onto our site.  They sign on, click a link that generates the post that is being validated, the validation fails, they get our error page, they click back, post again, and all is well.  </p>
  
  <p>I can't figure out at all what is happening.  </p>
  
  <p>I looked in the MVC source code and I found a few places where an exception with the description "A required anti-forgery token was not supplied or was invalid" would be thrown.  The first is when the token is being deserialized in AntiForgeryDataSerializer.cs.  This isn't where our problem is though because in this case, the exception is thrown with an inner exception that describes the actual serialization problem.  We are logging inner exceptions and we aren't logging one in this case.  </p>
  
  <p>The other place this exception is thrown is in the Validate method in AntiForgeryWorker.cs.  Here, the exception is being thrown without an inner exception, so the problem must lie in this code somewhere.  It looks like this:</p>
  
  <pre><code>public void Validate(HttpContextBase context, string salt) {
      Debug.Assert(context != null);
  
      string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
      string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);
  
      HttpCookie cookie = context.Request.Cookies[cookieName];
      if (cookie == null || String.IsNullOrEmpty(cookie.Value)) {
          // error: cookie token is missing
          throw CreateValidationException();
      }
      AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);
      string formValue = context.Request.Form[fieldName];
      if (String.IsNullOrEmpty(formValue)) {
          // error: form token is missing
          throw CreateValidationException();
      }
      AntiForgeryData formToken = Serializer.Deserialize(formValue);
       if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
              // error: form token does not match cookie token
              throw CreateValidationException();
          }
  
          string currentUsername = AntiForgeryData.GetUsername(context.User);
          if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
              // error: form token is not valid for this user
              // (don't care about cookie token)
              throw CreateValidationException();
          }
  
          if (!String.Equals(salt ?? String.Empty, formToken.Salt, StringComparison.Ordinal)) {
              // error: custom validation failed
              throw CreateValidationException();
          }
      }
  </code></pre>
  
  <p>One of those is throwing the exception.  I'm not using a salt so that throws out the last one.  I look in the IIS logs and I see the cookie, it's not that the cookie is missing.  So it's either that the form value is missing (unlikely, I would think), that the values don't match, or that the user name doesn't match.  I'm at a loss.  I can't reproduce this so I really can't debug.  It seems to happen to the same users over and over, but I can't come up with a pattern in what they're doing.  They have to have cookies on to even log into our site to get to this point, so that's not an issue.  Users will log in, make the form post, and get the error all within the span of 8-10 seconds.  They appear then to hit the back button after seeing our error page, try the post again, and it's fine.</p>
  
  <p>Any thoughts on how to proceed next?</p>