nickjj / build-a-saas-app-with-flask

Learn how to build a production ready web app with Flask and Docker.
https://buildasaasappwithflask.com
MIT License
954 stars 185 forks source link

CSRF problem #34

Closed treldor closed 8 years ago

treldor commented 8 years ago

hello nickjj

i am seeing csrf token missing or invalid error in production server

i thought maybe because of import error in all Forms.py:

import Form from wtforms << no csrf protection import Form from flask.ext.wtf << usually do like this

see here last section Troubleshooting: http://flask-wtf.readthedocs.org/en/latest/csrf.html

But still not working! i am seeing csrf error when i try to login. i have secret key in settings.py file

nickjj commented 8 years ago

Is the same SECRET_KEY being used in instance/settings.py? Because that one is going to "win" vs the one in config/settings.py. If you recently switched the key, you would need to restart your server for it to take effect.

Is it a custom form you've added to the project? Is it being executed via ajax or a regular submission?

CSRF tokens get injected into all forms created with this macro due to L75: https://github.com/nickjj/build-a-saas-app-with-flask/blob/master/catwatch/templates/macros/form.jinja2#L59

There's also this as well for ajax submissions: https://github.com/nickjj/build-a-saas-app-with-flask/blob/master/catwatch/templates/layouts/base.jinja2#L12

You will need to adjust your ajax calls to use that meta tag like so: https://github.com/nickjj/build-a-saas-app-with-flask/blob/master/catwatch/assets/scripts/stripe.js#L115 https://github.com/nickjj/build-a-saas-app-with-flask/blob/master/catwatch/assets/scripts/stripe.js#L80-L89

treldor commented 8 years ago

its not ajax or custom just the normal sign in or sign up > csrf token invalid or missing

nickjj commented 8 years ago

Sounds like there might be something wrong in your production environment because it sounds like it's working in development?

treldor commented 8 years ago

yes it work in development! but what can be wrong? only SECRET_KEY in settings/instance.py is different should be defined anywhere else?

treldor commented 8 years ago

csrf only depend on SECRET_KEY value correct?

nickjj commented 8 years ago

You might be using an old version of the secret_key and you're getting a mismatch. Try restarting Flask.

treldor commented 8 years ago

i do: sudo systemctl restart docker still not work, same csrf error

should SECRET_KEY only be in instance/settings.py?

nickjj commented 8 years ago

It should be in both. config/settings.py will be used in development and instance/settings.py will be used in production or any environment where you'd want to protect sensitive data.

treldor commented 8 years ago

only SECRET_KEY affect CSRF correct?

treldor commented 8 years ago

also does ssl certificate? because i didn't do that step yet, still unsecured

nickjj commented 8 years ago

Flask-WTF mentions that it uses SECRET_KEY in their docs here: https://flask-wtf.readthedocs.org/en/v0.8.3/#configuring-flask-wtf

Lack of SSL wouldn't effect anything with CSRF warnings/errors.

treldor commented 8 years ago

unfortunately not work SECRET_KEY is in instance/settings.py CSRF error on all form login/signup/issue

any good idea?

nickjj commented 8 years ago

I would need much more detail but it sounds like the code itself is working because it runs fine in development. There must be something in your deploy pipeline that's causing a mix up somewhere.

treldor commented 8 years ago

i can even see CSRF token in developer tools in browser from production server

correct, code working fine in development, only thing different i can think of in production is settings/instance.py this (sorry for big post):

ANALYTICS_GOOGLE_UA = 'XXX'

SERVER_NAME = '46.XXX.XXX.XXX'

SECRET_KEY = 'complexpassword' WTF_CSRF_ENABLED = True DEBUG = False LOG_LEVEL = 'INFO'

MAIL_USERNAME = 'you@example.com' MAIL_PASSWORD = 'thebestpasswordyouevermade'

db_uri = 'postgresql://catwatch:bestpassword@postgres:5432/catwatch' SQLALCHEMY_DATABASE_URI = db_uri SQLALCHEMY_POOL_SIZE = 25

CACHE_REDIS_URL = 'redis://redis:6379/0'

CELERY_BROKER_URL = 'redis://redis:6379/0' CELERY_RESULT_BACKEND = 'redis://redis:6379/0' CELERY_REDIS_MAX_CONNECTIONS = 25

APP_NAME = 'catwatch'

elie-h commented 8 years ago

If it's slowing you down you could disable CSRF as a temporary workaround: By adding WTF_CSRF_ENABLED = False in instance/settings.py

If that stops the CSRF error then you'll be sure your settings file is being read by the app.

nickjj commented 8 years ago

There's nothing wrong with that config. It's likely due to you changing your secret_key and either not copying a fresh version of this file to your server, or forgetting to restart flask.

Double check everything on your server.

nickjj commented 8 years ago

Closing this as there's an entirely new code base.