We had this problem: our application worked well on desktop but on phone any action had CSRF problem.
Mm, strange. Soon we discovered it's problem only with Android. Later we were sure it's only Chrome on Android. Even stranger!
Next step we did was to check what we are using exactly for CSRF validation. Django. Without customization. Of course, no one had this issue by checking Google, so it had to be some problem with our configuration. But it worked everywhere else…
We found that same cookie was used for our top domain and our application runs on sub-domain. It could be an issue, all browsers can handle it but Chrome on Android has some problem with that, we thought. We changed it. Deployed it. And nothing!
Ok, time to plug the phone and open debug tool to see what's happening. In development environment, everything worked just fine. That's very strange and because of that we were still checking configuration for few more minutes. Without success.
After hour or so we noticed that token was really wrong. Token in response from the server was different than which was then set up to the session. We didn't know what to check next so we did the worst thing possible. Add some logging on the server and see what's happening. We noticed some regeneration of token. Why it's regenerated? And why there is more then one request when using phone?!
And then we finally saw it. Android is doing one request for a page user wants and one for some special 96px version of icon it could be used… somewhere. Which generates 404 page and we have some form at every page. But Django (it took us another half an hour, probably more) doesn't use CSRF middleware for 404 and 500 pages! Which means Django is not going to take token from cookie and when token is needed, new one is generated!
Fix is to use decorator for 404 and 500 views, as described in Django documention. It's there, but who would expect that.
Half of the day. We spent half of the day, two of us, to figure out this issue. I really don't know how to explain to people why development of simple websites cost so much money. Better to just laugh, take a glass of whisky and watch Django Unchained. Much more fun than debug Django app. :-P