Closed rubenwardy closed 2 weeks ago
I investigated the topic and here what I found.
In the current state of the project, all CSRF protection is managed by flask_wtf.csrf.CSRFProtect
.
flask_wtf.csrf.CSRFProtect
sets up the template function csrf_token
which is an alias for flask_wtf.csrf.generate_csrf
.
flask_wtf.csrf.CSRFProtect
also sets up a middleware (with @app.before_request
), which extracts CSRF token from the request (from form data or HTTP header) and calls flask_wtf.csrf.validate_csrf
.
flask_wtf.csrf.generate_csrf
does the following:
create a random value and save it as session["csrf_token"]
, if the value was not previously set
sign this value with WTF_CSRF_SECRET_KEY
and current time and return the result from the function
flask_wtf.csrf.validate_csrf
does the following:
check if the token from the request is not empty and session["csrf_token"]
is set
check if the token signed with correct signature and the signature is not older than WTF_CSRF_TIME_LIMIT
check if the token and session["csrf_token"]
are equal
This means that there is no such thing as invalidation of CSRF tokens. Tokens when created are signed with current time, and when checked can be considered expired if the signature is too old.
In fact flask_wtf.csrf
implements Signed Double Submit Cookie technique with HMAC CSRF Token, recommended by OWASP Cheat Sheet Series (link). This cheat sheet also states that including timestamps in CSRF token is a common misconception, and CSRF tokens do not need to expire.
WTF_CSRF_TIME_LIMIT = None
config parameter can be used to disable CSRF token expiration. documentation
If you take a long time to write a review, thread, or comment, the content can be swallowed by CSRF. (Apparently submitting a form invalidates all CSRF tokens?)
Instead, the user should be returned to the form with an error saying to resubmit