Apparently Random Error: "Antiforgery token validation failed. The antiforgery cookie token and request token do not match."
See original GitHub issueBackground
I have a relatively new ASP.NET Core 2 site. It’s running on just one server (Windows Server 2012 R2, IIS 8.5), and I only restart the site once every few days when I upload an update. About once a day, a user’s request fails due to rejection by the anti-forgery system. These are POST requests, and there’s nothing particularly special about them. I’m including the anti-forgery value in the POST request, and 99% of the time, POST requests work. But when they don’t, the stdout log says, “Antiforgery token validation failed. The antiforgery cookie token and request token do not match.” I’ve already posted this question on Stack Overflow and the ASP.NET Core forums, and I haven’t gotten any useful answers.
Errors
I’ve included the relevant portions of the stdout log below.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 POST [domain redacted] application/x-www-form-urlencoded 234
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ValidateAntiforgeryTokenAuthorizationFilter[1]
Antiforgery token validation failed. The antiforgery cookie token and request token do not match.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery cookie token and request token do not match.
at Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
at Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.<ValidateRequestAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ValidateAntiforgeryTokenAuthorizationFilter.<OnAuthorizationAsync>d__3.MoveNext()
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.AutoValidateAntiforgeryTokenAuthorizationFilter'.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 400
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[2]
Executed action /Index in 2.6224ms
warn: Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery[1]
Antiforgery validation failed with message 'The antiforgery cookie token and request token do not match.'.
For requests that result in the above stdout output, IAntiforgery.IsRequestValidAsync agrees by returning false. Notice the error message “The antiforgery cookie token and request token do not match.” Here’s a reduced example of a failed POST request and the associated cookie.
POST: __RequestVerificationToken= CfDJ8F9Fs4CqDFpLttT96eZw9WHjWfHO8Yawn35k4Yq3gDK5n1TDJDDiY5o86VQs1_qOVIYBydCizBU4knb7Jmq1-heGhwnMu2KmhUIiAd0xI7Sudv3GX-J0OI6wRfiPL4L1KRs2Pml8dbsDfwemewBqi18
Cookie: .AspNetCore.Antiforgery.ClRyCRmWApY=CfDJ8F9Fs4CqDFpLttT96eZw9WFtJht41WcNrmgshi2pFGwcxhr0_0hvINQc7Yl9Cbjhv-TiSNXeEctyKborLI49AcjHfWIgOmmKkbjOe7QMn8Z0WZtkQy5JcaBHKEGTu1p-La8JL8pZZqZy02Hrswpkh3I
I’ve also captured this data a few times after the request has failed with a 400 error (using some error handling middleware):
AntiforgeryTokenSet tokens = antiforgery.GetTokens(context);
tokens.CookieToken: null
tokens.FormFieldName: "__RequestVerificationToken"
tokens.HeaderName: "RequestVerificationToken"
tokens.RequestToken: "CfDJ8F9Fs4CqDFpLttT96eZw9WH33jSw5mM8h7RpEd3vGISQTRkx1rfwm-L2lfkvXKMBc-riESmoTo_fnIjeBbRmOo5KuJHr09f8B75sQ9g_djIVeeaGwMw5KE6W1O2-7Vi03fCnwlTv8l-BWGst76Ln-ZQ"
So here are the three strings:
POST String: "CfDJ8F9Fs4CqDFpLttT96eZw9WHjWfHO8Yawn35k4Yq3gDK5n1TDJDDiY5o86VQs1_qOVIYBydCizBU4knb7Jmq1-heGhwnMu2KmhUIiAd0xI7Sudv3GX-J0OI6wRfiPL4L1KRs2Pml8dbsDfwemewBqi18"
Cookie String: "CfDJ8F9Fs4CqDFpLttT96eZw9WFtJht41WcNrmgshi2pFGwcxhr0_0hvINQc7Yl9Cbjhv-TiSNXeEctyKborLI49AcjHfWIgOmmKkbjOe7QMn8Z0WZtkQy5JcaBHKEGTu1p-La8JL8pZZqZy02Hrswpkh3I"
antiforgery.GetTokens(context).RequestToken: "CfDJ8F9Fs4CqDFpLttT96eZw9WH33jSw5mM8h7RpEd3vGISQTRkx1rfwm-L2lfkvXKMBc-riESmoTo_fnIjeBbRmOo5KuJHr09f8B75sQ9g_djIVeeaGwMw5KE6W1O2-7Vi03fCnwlTv8l-BWGst76Ln-ZQ"
The POST string and cookie string don’t match, but in my experience, even with requests ASP.NET Core considers legitimate, they never do. But strangely, the POST string and tokens.RequestToken don’t match either. I would think they should match, although I captured tokens.RequestTooken later in the request lifecycle, so maybe that has something to do with it.
ASP.NET Core 2 on GitHub
I decided to look at the source code of ASP.NET Core 2. I found this file, especially line 145:
That line gets the message “The antiforgery cookie token and request token do not match.” from this file at line 134:
https://github.com/aspnet/Antiforgery/blob/dev/src/Microsoft.AspNetCore.Antiforgery/Resources.resx
So I think that’s where the message is originating, but I’m still left wondering why this is happening.
Question
Would someone please help me figure out why these anti-forgery tokens aren’t validating? Is it possible the user’s Web browser is mangling the cookie or POST data? Does anyone have experience in this area or any suggestions? Thank you.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:3
- Comments:51 (18 by maintainers)
Top Related StackOverflow Question
We’ve been experiencing this problem for several years in a production application on ASP.NET MVC 5 (though similar anti-forgery mechanism to ASP.NET Core). Our application has a few components that are mini-single-page-applications. So, there’s a lot of requests via JavaScript that we do that include anti-forgery protection. We’ve been able to prevent anti-forgery errors by introducing a couple of changes:
localStoragesessionevents or using the Broadcast Channel API) and show a message on the “stale” tab. A lot of sites do this similar pattern (e.g. GitHub, AWS Console, etc). This reduced a large majority of our problems.Although this fixed most of our problems, we still have had consistent anti-forgery problems from some of our users. We have a heartbeat-like request that sends useful information for aggregating/reporting later on in the user interface. This heartbeat-like request would continuously fail for certain users meaning that their data was lost and couldn’t be reported on. Thankfully, the anti-forgery error was transparent to them but it meant a discrepancy in data for reporting.
In a recent investigation back into this problem, I found some interesting revelation in our logs:
Here’s what this is caused by:
/applesand/bananas).__RequestVerificationTokencookie is cleared because it’s only alive for as long as the browser’s session..ASPXAUTHcookie is not cleared because it has a default expiration of 1 year./applesand/bananasare launched concurrently in our app. This could also be accomplished just by doing something like middle-clicking on a tab more than once, but the pattern seems to fit since this causes the referrer to be empty. Both of those pages render a form with the anti-forgery token (e.g.@Html.AntiForgeryToken()).__RequestVerificationTokencookie and send it as part of the response because the request does not have a__RequestVerificationToken. When the form’s token is generated during the request, it’s for the unique cookie token per-request.I have some ideas to work around this, though I haven’t fully thought them through:
Does anyone else have any ideas on how we could solve this problem? @wessleym I’m not entirely sure if any of this can help solve your problem but I hope it may be able to provide some insight.
If it’s worth something, iv’e been facing this issue since ASP.NET MVC 5. As it is described it happens 1 on 1000 times apparently random. No matter how hard I try, I still cannot reproduce this behaviour