Failed to Acquire a Token for the Requested Resource
Gear up Missing CSRF Token Issues with Flask
Acquire how to prepare bad request / CSRF token missing errors with Flask that stalk from bugs with webkit based browsers.
Quick Spring: You Did Everything the Docs Stated | What Does Your Dev Environment Look Like? | What Causes Bad Request CSRF Token Missing? | Easily Set up the Problem for the Fourth dimension Being | An Exercise in Debugging
There may come a time in your life where you're absolutely sure that you lot have Flask-WTF configured properly in your awarding.
Yous Did Everything the Docs Stated
For starters, you've instantiated and exported CsrfProtect like so:
# myapp/extensions.py from flask_wtf import CsrfProtect csrf = CsrfProtect () You've also imported it into your app.py file:
# myapp/app.py from myapp.extensions import csrf Then you've initialized it onto your Flask app:
# myapp/app.py def create_app (): app = Flask ( __name__ ) app . config . from_object ( 'config.settings' ) csrf . init_app ( app ) Finally, yous've included the proper tag in your form template:
<class action= "{{ url_for('myform') }}" method= "mail service" role= "grade" > {{ form.hidden_tag() }} <!-- The rest of your form goes hither. --> </class> Yet Information technology Still Doesn't Work and Flask Throws a CSRF Related Fault
You may have tried to debug the issue past dropping this into your course's road:
print ( '------ {0}' . format ( request . form )) …and to your surprise the csrf_token value is empty. WTF?
You've probable also opened your dev tools in your browser and went to the resources tab to accept a look at your cookies. Oddly enough, it's empty.
What Does Your Dev Environs Wait Similar?
Chances are 2 things are happening in your environment:
- You're running Flask inside of a Docker Auto or are using Vagrant / etc.
- You are using Chrome, Opera, Edge, IE11 and mayhap others (just not Firefox or Safari)
It may too be due to using an AWS EC2 instance'south public DNS hostname, only more on that later.
If your Flask server is not running on localhost then in order to get Flask to resolve URLs properly, you've likely modified the SERVER_NAME value somewhere.
For case, you might accept something similar this in config/settings.py:
SERVER_NAME = '192.168.99.100:8000' This is what I recommend my students to do in the Build a SAAS App with Flask course if they happen to be using Docker Toolbox considering we use Docker.
What Causes Bad Request CSRF Token Missing?
This problem happens because of 2 things.
Firstly, there's a bug in webkit based browsers.
The spec for rejecting cookies states that domain names must be a fully qualified domain name with a TLD (.com, etc.) or be an exact IP address.
Update in 2017: It looks like the spec has changed to explicitly state no exact IP addresses, and so the bits most Chrome being buggy are no longer authentic.
Update in 2020: I recently discovered this also affects AWS EC2 public DNS hostnames. To exist honest I'm not certain why they are treated as a direct IP address, but you will go a missing CSRF token error if y'all apply your instance'southward public DNS hostname.
Chrome is too absurd to adhere to specifications, and then they decided to be more strict and deny verbal IP addresses. That means cookies won't exist set if you have an IP address based SERVER_NAME.
Ok, well that'due south pretty lame but acute readers might be thinking how does localhost work because that doesn't include a TLD.
That brings usa to the second thing, and nosotros can blame Flask for that.
The Flask author is a very talented programmer and 99.9% of the fourth dimension his decisions are for your benefit but in my opinion he screwed up with this one.
If you await at the Flask source to return the cookie domain he makes assumptions nigh your development surround.
Take a look at this block of code:
# Google chrome does non like cookies fix to .localhost, then # we just go with no domain then. if rv == '.localhost' : rv = None The Flask writer is definitely aware of the trouble just he hard codes a fix. I can't blame him because a lot of developers volition exist using localhost so it fixes the problem for those developers without them having to recollect virtually information technology.
Nowadays Docker and virtualized development environments are much more than common, so IMO I'd similar to encounter this turned into a Flask config option then users can prepare which domain tin get ignored.
Easily Fix the Problem for the Time Being
The quickest way to fix this problem in development would be to modify your /etc/hosts file.
OSX and Linux users can observe that in /etc/hosts and Windows users tin observe information technology in C:\Windows\System32\drivers\etc\hosts.
You volition need to open the file with elevated privileges, meaning y'all'll demand to open it with sudo or Ambassador privileges.
Add this line to the bottom of the file: 192.168.99.100 local.docker
Keep in listen, if your development IP address is not what's listed in a higher place so make the necessary adjustment to use yours instead.
Also feel free to modify local.docker to anything you want, as long every bit it includes a period so that it's a valid FQDN with a TLD.
For instance local.dev or local.host would exist valid but localfoo is not.
In the EC2 example case, you should make a proper DNS entry on a real domain name and admission your site in that location.
Updating Your Flask Config
The last thing y'all'll need to exercise is change your SERVER_NAME to friction match what we just created in the /etc/hosts file (or whatever your domain name is).
You lot'll want to gear up: SERVER_NAME = 'local.docker:8000' or whatsoever yous used.
At this bespeak you're proficient to go and everything should work great.
An Do in Debugging
This was an interesting issue to debug considering equally you may know, I create video tutorials and courses.
I recently created a form on Flask and I personally run Docker on Linux natively. I also happen to use FireFox which does adhere to the spec correctly.
When I ran through the material, everything worked great just then problems started to pour in from OSX users. Some OSX users were using Docker Toolbox to ready upwards their Docker environment, so they were using IP based server names.
However, not all OSX users were reporting this issue considering not everyone was using Chrome and Docker Toolbox. Needless to say, it wasn't an obvious solution, especially since I had students connect to my server through ngrok and successfully submit the form.
Where as, when I connected to their server it worked for me because I was using FireFox. And then when I tried Chrome on their server it failed, and that lead me to somewhen necktie in that the trouble had something to do with Chrome.
Other students reported the same problem on Safari so it seems to affect webkit in general.
The lesson hither is that y'all should accept zero for granted when it comes to debugging. Even the slightest change in environment can cause desperate differences in output.
Similar you, I'one thousand super protective of my inbox, and then don't worry about getting spammed. You lot tin expect a few emails per calendar month (at most), and you tin can ane-click unsubscribe at any time. See what else yous'll get too.
Source: https://nickjanetakis.com/blog/fix-missing-csrf-token-issues-with-flask
Postar um comentário for "Failed to Acquire a Token for the Requested Resource"