How can I use Flask WTForms and CSRF without session cookie?

Question:

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:

  1. What is the relationship between CSRF token validation and session cookie? Why is a cookie necessary to validated the CSRF token?
  2. 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.
  3. How can I use CSRF form validation without a session cookie?

Thank you so much.

Asked By: Neil

||

Answers:

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.

Answered By: Neil

You should check if it helps you:

https://wtforms.readthedocs.io/en/3.0.x/csrf/#creating-your-own-csrf-implementation

This allows you to create your own implementation of csrf token generation and validation in which you do not need to use cookies.

Answered By: krank