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." When I perform a Web search using that exact statement, I get zero results. So I've turned to Stack Overflow. [This is no longer true as a Web search now yields this Stack Overflow question.]
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.RequestToken
later in the request lifecycle, so maybe that has something to do with it.
I decided to look at the source code of ASP.NET Core 2. I found this file, especially line 145:
https://github.com/aspnet/Antiforgery/blob/dev/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenGenerator.cs
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.
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.
Disabling the filter globally seems to be the only way to turn it off. I got @svallis's code to work with a sight modification:
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
});
https://github.com/aspnet/Mvc/issues/7012
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With