title: Flask-WTF CSRF validation fails when app moved to docker production environment
body: <p>I just set up my production environment for the Flask app I've been developing.</p>
  <p>This stack is:</p>
  <pre><code>Windows Server 2012 R2 
  Hyper-V VM 
      - Running Ubuntu 14.04
  Docker 1.5 
      - Running Containers: 
          mysql 5.6
          nginx 1.6.3
          uwsgi 2.0.10
  </code></pre>
  <p>So basically I have a static IP set up in Ubuntu, port 80 getting forwarded to the nginx container, a data volume shared between the nginx and uwsgi containers for a socket file, and finally a link between the mysql container and the uwsgi container for database communication.</p>
  <p>I've been using CSRF in the below implementation in my local development environment for awhile now with no issues:</p>
  <pre><code>from flask_wtf import Form
  
  class UserForm(Form):
      ...
  </code></pre>
  <p>And then in my template:</p>
  <pre><code>&lt;form&gt;
      {{ form.hidden_tag() }}
      ...
  &lt;/form&gt;
  </code></pre>
  <p>However when I moved my app, unchanged, to the environment specified above, I get:</p>
  <blockquote>
  <p>Bad Request</p>
  <p>CSRF token missing or incorrect.</p>
  </blockquote>
  <p>in response when I attempt to submit a form. I am using the same exact requirements.txt file with pip to setup my Flask app. I've also verified that the CSRF token is indeed in the HTML of the page.</p>
  <p>Anyone have any clue as to why this is happening?</p>
  <p><em>EDIT:</em></p>
  <p>To answer the questions in the comments: The version of Flask-WTF and WTForms in both my production docker container and my development local virtualenv are the same. Here's my requirements file, spawned from my dev environment and used to set up my app inside the docker container:</p>
  <pre><code>Flask==0.10.1
  Flask-Login==0.2.11
  Flask-Mail==0.9.1
  Flask-Migrate==1.2.0
  Flask-MySQL==1.2
  Flask-Principal==0.4.0
  Flask-SQLAlchemy==2.0
  Flask-Script==2.0.5
  Flask-Security==1.7.4
  Flask-WTF==0.10.2
  Flask-WhooshAlchemy==0.55a
  Jinja2==2.7.3
  Mako==1.0.0
  MarkupSafe==0.23
  PyMySQL==0.6.2
  SQLAlchemy==0.7.9
  Tempita==0.5.2
  WTForms==2.0.1
  Werkzeug==0.9.6
  Whoosh==2.6.0
  alembic==0.6.7
  blinker==1.3
  chardet==2.2.1
  decorator==3.4.0
  itsdangerous==0.24
  lamson==1.3.4
  passlib==1.6.2
  py-bcrypt==0.4
  pytz==2014.9
  sqlalchemy-migrate==0.7.2
  </code></pre>
  <p>That being said, there are a couple extra modules in my docker container due to installing uWSGI as well as my flask app. Here are the additional ones.</p>
  <pre><code>argparse (1.2.1)
  colorama (0.2.5)
  docutils (0.12)
  html5lib (0.999)
  lockfile (0.10.2)
  mock (1.0.1)
  MySQL-python (1.2.5)
  nose (1.3.6)
  python-daemon (2.0.5)
  python-modargs (1.7)
  requests (2.2.1)
  six (1.5.2)
  urllib3 (1.7.1)
  uWSGI (2.0.10)
  wheel (0.24.0)
  wsgiref (0.1.2)
  </code></pre>
  <p>Wow, so more than a couple. Perhaps I have a conflicting package?</p>
  <p>Regarding SECRET_KEY and CSRF_SESSION_KEY: I had SECRET_KEY defined in my config.py. I was lead to believe that without defining CSRF_SESSION_KEY that it would default to SECRET_KEY. Nevertheless, I went ahead and defined a CSRF_SESSION_KEY, but it didn't seem to make any difference.</p>
  <p>Lastly, I looked into the API change from {{ form.hidden_tag() }} to {{ form.csrf_token }}. They still have references to both forms in the docs for the latest version. On the CSRF page, they have the latter, but in the quickstart they still have the former. I'm not sure what is up with this, but just to be certain I implemented the version on the CSRF page as follows:</p>
  <p><strong>init</strong>.py:</p>
  <pre><code>from flask_wtf.csrf import CsrfProtect
  
  CsrfProtect(app)
  </code></pre>
  <p>user_login.html</p>
  <pre><code>&lt;form&gt;
      {{ form.csrf_token }}
      ...
  &lt;/form&gt;
  </code></pre>
  <p>But I still end up getting the same response.</p>
  <p>As I said before, the Flask-WTF documentation is all over the place. So I've been trying all sorts of combinations. At the bottom of this page: <a href="http://flask-wtf.readthedocs.org/en/latest/csrf.html" rel="nofollow noreferrer">http://flask-wtf.readthedocs.org/en/latest/csrf.html</a> they reference an incorrect import, so I replaced my</p>
  <blockquote>
  <p>from flask_wtf import Form</p>
  </blockquote>
  <p>with</p>
  <blockquote>
  <p>from flask.ext.wtf import Form</p>
  </blockquote>
  <p>Still no dice. Thanks for the comments though, gave me more to try out!</p>
  <p>I also just tried consolidating everything into a single docker container, but I still get the same result.</p>