Commit db21a600 authored by Andrew Grigorev's avatar Andrew Grigorev

Fix CSRF for production deployments

Current SecureForm implementation generates CSRF secret using
`os.urandom()` every time when application start up. CSRF secret is used
to calculate csrf_token check value, so if someone would use a command
similar to

    gunicorn --workers=8 app

to run his flask-admin app on production then most form submissions
would silently fail (silently - as for now, it is probably another one
bug).

Instead of custom `os.urandom()` logic the `app.secret_key` value should
be used to produce CSRF token values.
parent d7ee730a
...@@ -43,8 +43,9 @@ def recreate_field(unbound): ...@@ -43,8 +43,9 @@ def recreate_field(unbound):
if int(wtforms_version[0]) > 1: if int(wtforms_version[0]) > 1:
# only WTForms 2+ has built-in CSRF functionality # only WTForms 2+ has built-in CSRF functionality
from os import urandom from os import urandom
from flask import session from flask import session, current_app
from wtforms.csrf.session import SessionCSRF from wtforms.csrf.session import SessionCSRF
from flask_admin._compat import text_type
class SecureForm(BaseForm): class SecureForm(BaseForm):
""" """
...@@ -55,7 +56,14 @@ if int(wtforms_version[0]) > 1: ...@@ -55,7 +56,14 @@ if int(wtforms_version[0]) > 1:
class Meta: class Meta:
csrf = True csrf = True
csrf_class = SessionCSRF csrf_class = SessionCSRF
csrf_secret = urandom(24) _csrf_secret = urandom(24)
@property
def csrf_secret(self):
secret = current_app.secret_key or self._csrf_secret
if isinstance(secret, text_type):
secret = secret.encode('utf-8')
return secret
@property @property
def csrf_context(self): def csrf_context(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment