A common technique against CSRF attacks is to add a random string to the session, and check that string against a hidden field in the POST.
@app.before_request
def csrf_protect():
if request.method == "POST":
token = session.pop('_csrf_token', None)
if not token or token != request.form.get('_csrf_token'):
abort(403)
def generate_csrf_token():
if '_csrf_token' not in session:
session['_csrf_token'] = some_random_string()
return session['_csrf_token']
app.jinja_env.globals['csrf_token'] = generate_csrf_token
And then in your template:
<form method=post action="">
<input name=_csrf_token type=hidden value="{{ csrf_token() }}">
This snippet by Dan Jacob can be used freely for anything you like. Consider it public domain.
Comments
abort instead of exception by Armin Ronacher on 2010-05-03 @ 11:42
I would recommend using
abort(400)instead ofraise Forbidden. First of all it's part of the Flask API (theabort) function and it also matches HTTP better here. It is a bad request and not really a forbidden URL.403 used in Django by Dan Jacob on 2010-05-03 @ 11:55
Sure - the main reason I used 403 was because (rightly or wrongly) that's what Django uses:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#rejected-requests
Missing name attr by justquick on 2010-05-04 @ 06:13
One last thing I saw missing while trying to get this up myself is the hidden input field is missing the name attribute. It should be
PS - its working wonderfully now
Last line typo by justquick on 2010-05-04 @ 04:38
The last line should read
I also think that abort(403) is the best way to handle this
Last line update by Max Countryman on 2011-02-23 @ 22:51
I believe
`app.jinja_env.globals['csrf_token'] = generate_csrf_token`
should be
`app.jinja_env.filters['csrf_token'] = generate_csrf_token`
Please disregard by Max Countryman on 2011-02-24 @ 00:00
I'm sorry, I was wrong about the above post. Please disregard/remove.
What about JSON API? by Shuhao on 2012-06-21 @ 00:44
How would you protect yourself against CSRF if you have JSON apis?
re: What about JSON API? by Nick on 2012-08-22 @ 10:37
Just define a GET method which returns the CSRF token.
how to handle session timeouts by Andrew Kloos on 2012-10-29 @ 18:20
Let's say someone navigates to your page which contains a form with your csrf token. Now let's says they wait on the page and their session timeout out. How do you handle them posting while their session has already timed out? Thanks!