Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Anti-forgery cookie errors. What's the cause? #158

Open
TFAstudio opened this issue Oct 29, 2019 · 10 comments
Open

Anti-forgery cookie errors. What's the cause? #158

TFAstudio opened this issue Oct 29, 2019 · 10 comments

Comments

@TFAstudio
Copy link

We've been using Formulate for many years but started getting occasional server errors after we upgraded a couple of customers to a new version (for Umbraco v7) back in September 2019. These are all single-server hosting environments (no load-balancing etc).

The errors are reported from a range of mobile phones including iPhone (OS 10.3.2, 11.4.1, 12.3.1, 12.4 etc), and Android 8 & 9 (mainly Samsung but also Pixel 2 & Pixel 3). Almost no desktop environments are seemingly affected (only a few errors from Windows NT 10.0). Reported IP addresses all correlate to Australian mobile service companies (and the occasional ISP) and look like legitimate local traffic.

Most common error is:
_System.Web.Mvc.HttpAntiForgeryException (0x80004005): The required anti-forgery cookie "_RequestVerificationToken" is not present.

But we also get these occasionally:
System.Web.Mvc.HttpAntiForgeryException (0x80004005): The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.

They happen a few times per week and we haven't been able to replicate the behaviour. We normally get a string of errors from the same IP address, indicating that a frustrated user is trying to resubmit a form repeatedly.

I've tried to research what could be causing these errors but had little luck. Perhaps IIS & hosting related? Any ideas will be gratefully welcomed.

@Nicholas-Westby
Copy link
Contributor

I don't have any real answers, but I have some theories.

On the initial request for a page, Formulate responds with both a cookie and JSON value. These are served in pairs. If there is some sort of mismatch, an error would occur during form submission.

One scenario I can imagine this in would be if the visitor comes to a page, the server restarts, then they try to submit the form. Or, the visitor comes to a page, they wait a long time, then they try to submit the form.

I'm thinking something could go haywire in either of those situations that would cause the token to not be verified upon form submission (e.g., maybe the server has some encryption component stored in memory that it changes on a schedule or on app pool recycles).

Another thing that might cause this would be if cookies are disabled. The form would not be able to match up the two parts of the token in that case.

One more thing I could imagine would be a single-page app. If the user is navigating around the site and parts of the page aren't refreshing (e.g., the header and footer) and those parts of the page contain a form, the cookie might not match the JSON value.

@Nicholas-Westby
Copy link
Contributor

Oh, and certain forms of caching might also lead to this. Like when the visitor clicks the back button, or a WAF cache like Cloudflare.

@TFAstudio
Copy link
Author

Some of the things you've mentioned I have read about in my research (none of which resulted in directly related answers). Your suggestions are excellent discussion starters, thank you.

I'm certainly one to leave a tab open in a browser (mobile or desktop) for days or weeks. If such a page isn't refreshed when refocused, I can see how old cookie or session values might be affected.

Our servers (and application pool) restart very rarely. Although this would likely clear the server-side anti-forgery tokens, there doesn't seem to be any correlation in these cases. So possible, but a long-shot for us I think, at least for the majority of instances. Of course, this might tie into the "open tabs" point. If users kept the partially filled-out form open for weeks, the server might have rebooted by the time they complete their submission.

Cookies disabled. I wonder how common that is on Mobile devices... I wonder if displaying a front-end error on form-load would be worthwhile here. Ie. "Cookies are disabled in your browser, you will be unable to submit this form." I guess ad blockers could possibly play a part here too.

Single page app tip is noted. Again, not applicable to our use cases.

@Nicholas-Westby
Copy link
Contributor

Here's somebody else who seems to think it has to do with session expiration: dotnet/aspnetcore#2882 (comment)

And one person mentioned it can be caused by mixing HTTP/HTTPS: https://stackoverflow.com/a/28786181/2052963

If we can find some simple way to reproduce the issue, that'd be the first step toward finding a fix. And since it seems like there are many things that might hypothetically cause this, I'd be most interested in solving whatever particular issue(s) you are running into.

Since this may be specific to mobile devices, it may be worth mentioning that I tend to default to incognito mode and leave tabs open for months on my phone. If others do that, might be a contributing factor.

In case you want to review how the code is managing the token, here are some links:

@SunSha
Copy link

SunSha commented Jun 16, 2020

Exactly the same issue, the same range of devices. Have you found any solution or the cause?

@Nicholas-Westby
Copy link
Contributor

I have not been able to reproduce the issue. If you can produce a reliable set of steps that demonstrate the issue, that would be a good first step toward resolving it.

@patcor
Copy link

patcor commented Sep 28, 2020

I was facing a similar issue where some requests were failing with 400 error due to AntiForgery validation error.
Similar issues are also mentioned in this thread: dotnet/aspnetcore#2882

For me the issue was due to SameSite setting.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

This means that when you make a new request OR a third party site redirects to any of your pages then the AUTH cookie will NOT be sent in the request header.

The flow was like this.

  1. Our site redirect to third party site
  2. Third party site redirects to our site
  3. The user submits a form
  4. 400 Error happen

But this would work perfect.

  1. Our site redirect to third party site
  2. Third party site redirects to our site
  3. Manually press F5 to refresh the page (after redirect)
  4. The user submits a form
  5. Works as expected

As stated, this happen because with Strict setting of the SameSite-policy for the cookie, then the cookies will not be sent even though the domain is the correct, it will only be sent during navigation on the same domain. Because the cookie is not sent in the first load of the page the anti forgery token will be set as "anonymous user", and then when we send the form the auth cookies IS sent and therefore the validation will fail.

I know that there are more possible issues than the SameSite-setting, but I hope this might help someone else with the same issue.

@intenzive
Copy link

@patcor, so what is the setting for the AntiForgery cookie you have selected - Lax?

@patcor
Copy link

patcor commented Dec 24, 2020

@patcor, so what is the setting for the AntiForgery cookie you have selected - Lax?

Yes, changing to lax solved the issue.

@monty241
Copy link

monty241 commented Jul 11, 2021

In our HTTPS-app on ASP.NET Core deployed on 5.0, this error occurs during user signup (and well before login):

Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: 'The antiforgery cookie token and request token do not match.'

The error occurs only when the cookie name is set using for instance:

services.AddAntiforgery(options =>
{
  options.Cookie.Name = ".Acme.Cloud.Antiforgery.";
});

Introducing something more unique as a name doesn't help:

  string somewhatRandomHash = Encryption.DetermineChecksum(owner, executionOptions, $"{DateTime.UtcNow.Ticks}").Substring(0, 8);
  options.Cookie.Name = string.Concat(".Acme.Cloud.Antiforgery.", somewhatRandomHash);

nor it helps to fiddle around with the form and header names:

  options.FormFieldName = "__AcmeRequestVerificationToken";
  options.HeaderName = "__AcmeRequestVerificationToken";

The problem also occurs in incognito mode in Chrome. The

Completely disabling the custom cookie name solves the AntiforgeryValidationException.

It is also weird that even with a standard cookie name the values of the .AspNetCore.Antiforgery.m_VdDo0sy3Q and __RequestVerificationToken differ. Nonetheless, no exception is raised.

Pending further analysis, we have disabled the custom naming of cookies.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants