The Csrf Token Is Invalid. Please Refresh and Try Again!

Fix Missing CSRF Token Issues with Flask

blog/cards/fix-missing-csrf-token-issues-with-flask.jpg

Larn how to fix bad request / CSRF token missing errors with Flask that stem from bugs with webkit based browsers.

Quick Leap: You Did Everything the Docs Stated | What Does Your Dev Environs Look Like? | What Causes Bad Asking CSRF Token Missing? | Hands Fix the Problem for the Fourth dimension Existence | An Practise in Debugging

There may come a time in your life where you're absolutely certain that you lot have Flask-WTF configured properly in your application.

You Did Everything the Docs Stated

For starters, y'all've instantiated and exported CsrfProtect like so:

                          # myapp/extensions.py              from              flask_wtf              import              CsrfProtect              csrf              =              CsrfProtect              ()                      

You've besides imported it into your app.py file:

                          # myapp/app.py              from              myapp.extensions              import              csrf                      

So 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, you've included the proper tag in your form template:

                          <course              action=              "{{ url_for('myform') }}"              method=              "post"              function=              "form"              >              {{ grade.hidden_tag() }}              <!-- The rest of your form goes hither. -->              </form>                      

Y'all may have tried to debug the effect by dropping this into your grade'due south road:

                          impress              (              '------ {0}'              .              format              (              asking              .              form              ))                      

…and to your surprise the csrf_token value is empty. WTF?

You've probable too opened your dev tools in your browser and went to the resources tab to take a look at your cookies. Oddly enough, it's empty.

What Does Your Dev Environment Expect Like?

Chances are two things are happening in your environment:

  1. Y'all're running Flask inside of a Docker Machine or are using Vagrant / etc.
  2. You are using Chrome, Opera, Border, IE11 and perhaps others (just not Firefox or Safari)

Information technology may likewise be due to using an AWS EC2 example's public DNS hostname, but more on that later.

If your Flask server is not running on localhost and then in guild to get Flask to resolve URLs properly, you've likely modified the SERVER_NAME value somewhere.

For example, you lot might have something like this in config/settings.py:

                          SERVER_NAME              =              '192.168.99.100:8000'                      

This is what I recommend my students to exercise in the Build a SAAS App with Flask course if they happen to be using Docker Toolbox because we use Docker.

What Causes Bad Request CSRF Token Missing?

This problem happens because of two 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 proper name with a TLD (.com, etc.) or be an exact IP address.


Update in 2017: It looks like the spec has inverse to explicitly state no exact IP addresses, so the $.25 about Chrome being buggy are no longer accurate.

Update in 2020: I recently discovered this likewise affects AWS EC2 public DNS hostnames. To be honest I'm non sure why they are treated as a direct IP address, but y'all volition get a missing CSRF token mistake if yous use your instance'due south public DNS hostname.


Chrome is too cool to adhere to specifications, and so they decided to be more strict and deny exact IP addresses. That means cookies won't be set if you lot take an IP address based SERVER_NAME.

Ok, well that'due south pretty lame simply acute readers might be thinking how does localhost piece of work because that doesn't include a TLD.

That brings us to the second thing, and nosotros can arraign Flask for that.

The Flask author is a very talented developer and 99.nine% of the time his decisions are for your benefit only in my opinion he screwed up with this ane.

If you wait at the Flask source to render the cookie domain he makes assumptions about your development environment.

Accept a await at this block of lawmaking:

                          # Google chrome does not similar cookies set to .localhost, so              # we just go with no domain and then.              if              rv              ==              '.localhost'              :              rv              =              None                      

The Flask writer is definitely enlightened of the problem only he hard codes a ready. I can't blame him because a lot of developers volition be using localhost so it fixes the trouble for those developers without them having to think about it.

Nowadays Docker and virtualized development environments are much more common, so IMO I'd similar to see this turned into a Flask config choice so users tin ready which domain tin get ignored.

Easily Prepare the Problem for the Time Being

The quickest way to fix this problem in development would be to change your /etc/hosts file.

OSX and Linux users can notice that in /etc/hosts and Windows users can notice information technology in C:\Windows\System32\drivers\etc\hosts.

You will need to open the file with elevated privileges, meaning you'll need to open it with sudo or Administrator privileges.

Add together this line to the bottom of the file: 192.168.99.100 local.docker

Continue in mind, if your development IP address is not what'south listed above then make the necessary adjustment to use yours instead.

Also feel free to change local.docker to annihilation you want, every bit long as information technology includes a period so that it'south a valid FQDN with a TLD.

For instance local.dev or local.host would be valid but localfoo is not.

In the EC2 instance example, you should brand a proper DNS entry on a real domain proper noun and access your site there.

Updating Your Flask Config

The last thing you'll need to do is alter your SERVER_NAME to match what we just created in the /etc/hosts file (or whatever your domain name is).

You'll desire to set: SERVER_NAME = 'local.docker:8000' or whatever y'all used.

At this point you're skilful to go and everything should work great.

An Practise in Debugging

This was an interesting issue to debug because as you may know, I create video tutorials and courses.

I recently created a course on Flask and I personally run Docker on Linux natively. I as well happen to use FireFox which does adhere to the spec correctly.

When I ran through the material, everything worked not bad just so problems started to pour in from OSX users. Some OSX users were using Docker Toolbox to set up their Docker environs, then they were using IP based server names.

However, not all OSX users were reporting this consequence because non 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 grade.

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 tie in that the problem had something to practice with Chrome.

Other students reported the aforementioned trouble on Safari so information technology seems to bear on webkit in general.

The lesson here is that you should take nothing for granted when it comes to debugging. Fifty-fifty the slightest change in environment tin cause drastic differences in output.

Like yous, I'm super protective of my inbox, so don't worry about getting spammed. Y'all tin expect a few emails per month (at most), and yous can i-click unsubscribe at any time. See what else y'all'll get too.

maestasphered1978.blogspot.com

Source: https://nickjanetakis.com/blog/fix-missing-csrf-token-issues-with-flask

0 Response to "The Csrf Token Is Invalid. Please Refresh and Try Again!"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel