I have a very simple app that has no user management or any Flask-Login auth needs. It has forms, WTForms. All I want to do is collect some data submitted by the form. I could technically disable CSRF validation but Flask WTForms really urges me not to.
I'd like to disable flask session cookie in the browser because it seems unnecessary and I would need to put a cookie banner for GDPR compliance. So to avoid all that, I thought of disabling flask session cookie as follows:
class CustomSessionInterface(SecureCookieSessionInterface):
""" Disable session cookies """
def should_set_cookie(self, app: "Flask", session: SessionMixin) -> bool:
return False
# App initialization
app = Flask(__name__)
app.session_interface = CustomSessionInterface()
But doing so leads to a 500
error: "The CSRF session token is missing". However, looking at the HTML that was rendered has the following csrf token rendered properly:
<input id="csrf_token" name="csrf_token" type="hidden" value="ImI2ZDIwMDUxMDNmOGM3ZDFlMTI4ZTIzODE4ODBmNDUwNWU3ZmMzM2Ui.YhA2kQ.UnIHwlR1qLL61N9_30lDKngxLlM">
Questions:
- What is the relationship between CSRF token validation and session cookie? Why is a cookie necessary to validated the CSRF token?
- I tried enabling session cookies again, deleting the cookie in Chrome developer tools leads to the same error. So, indeed, session cookie seems to be absolutely necessary to validate CSRF token.
- How can I use CSRF form validation without a session cookie?
Thank you so much.
CodePudding user response:
I found out from the code base of WTForms: https://github.com/wtforms/flask-wtf/blob/565a63d9b33bf6eb141839f03f0032c03894d866/src/flask_wtf/csrf.py#L56
Basically, session['csrf_token']
is stored in the session and compared against the form.hidden()
tag (or form.csrf_token
) in the HTML body.
This is not clearly explained in the docs. But the codebase makes it clear. I guess there is no way to do CSRF protection without secure cookies.
The downside of this is that you can't get rid of cookies. I suspect, one could build a server-side session database, but then there are issues with scaling your Flask app horizontally.