Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-WTF set time limit on CSRF token

I'm currently using Flask-WTF v0.13.1, i have a few forms on my website, all created including the CSRF token.

For some reasons i have to set a different expiration on each form, so far i could set manually the time_limit value upon creating the csrf token.

I would like to update to the v0.14, according to the changelog time_limit is gone and there is no reference in the docs on how to change it anymore. Looking in the source code i saw that the form has a csrf_time_limit meta parameter.

I tried to set that parameter on my form:

from flask_wtf import FlaskForm

class myForm(FlaskForm):
    class Meta:
        csrf_time_limit = 7200

    content = TextAreaField('content')

Although debugging the csrf.py module i see that the validate_csrf_token of _FlaskFormCSRF is actually never called.

The method validate_csrf is called within the method protect() instead, in this case the meta parameter is never considered.

I don't understand if this is a bug of the package or if i'm missing something.

UPDATE:

Example code:

app.py

from flask import Flask, render_template, request
from flask_wtf.csrf import CSRFProtect
from flask_wtf import FlaskForm
from wtforms import IntegerField

csrf = CSRFProtect()
app = Flask(__name__)
app.config.update(dict(
    SECRET_KEY="super secret key"
))

csrf.init_app(app)

class MyForm(FlaskForm):
    class Meta:
        csrf_time_limit = 1

    id = IntegerField('id')

@app.route("/", methods=['GET', 'POST'])
def test_form_csrf():
    if request.method == 'POST':
        myForm = MyForm(request.form)
        print(myForm.id.data)

    return render_template('test_form.html', myForm= MyForm())

templates/test_form.html

<form method="post" action="/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
    {{ myForm.id }}
    <input type="submit" value="test" />
</form>

requirements.txt

click==6.7
Flask==0.12.2
Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1
WTForms==2.1

project structure

app.py
templates
|
--- test_form.html

To run the code,

FLASK_APP=app.py flask run

I also put a debug breakpoint on this line to check the actual value of time_limit, the value is always 3600.

like image 856
Riccardo Avatar asked Feb 06 '18 10:02

Riccardo


1 Answers

Following your changelog link, I looked through the commit and found these lines:

if time_limit is None:
    time_limit = current_app.config.get('WTF_CSRF_TIME_LIMIT', 3600)

Setting app.config['WTF_CSRF_TIME_LIMIT'] to some shorter value seems to work. I have set it to 30 seconds with app.config['WTF_CSRF_TIME_LIMIT'] = 30 and the form expired after that amount of time, but I have not tried a longer value than the default.

I am not sure if you can change an app.config value on the fly in order to hack your way around not being able to set an expiration per form.

like image 53
Matt Avatar answered Oct 14 '22 01:10

Matt