I'm running flask on app engine. I need to let users upload some files. For security reasons I have csrf = CsrfProtect(app) on the whole app, with specific url's exempted using the @csrf.exempt decorator in flask_wtf. (Better to implicitly deny than to implicitly allow.)
Getting an upload url from blobstore with blobstore.create_upload_url works fine, but the upload itself fails with a 400; CSRF token missing or incorrect.
This problem is on the development server. I have not tested it on the real server, since it is in production.
How do I exempt the /_ah/ path so the uploads work?
I would be inclined to use the approach outlined at http://flask-wtf.readthedocs.org/en/latest/csrf.html ...:
You can also disable CSRF protection in all views by default, by setting WTF_CSRF_CHECK_DEFAULT to False, and selectively call csrf.protect() only when you need. This also enables you to do some pre-processing on the requests before checking for the CSRF token:
The original example given at that page is:
@app.before_request
def check_csrf():
if not is_oauth(request):
csrf.protect()
but of course in your case you'd change it to:
@app.before_request
def check_csrf():
if not request.path.startswith('/_ah/):
csrf.protect()
Note that this is still default-deny -- every request demands CSRF protection... except those whose path starts with /_ah/, exactly as you require.
Okey, so the real problem was that I was giving an absolute url to the successpath argument (i.e. the first) of blobstore.create_upload_url(), causing the request notifying about the success caused a csrf error when loading the root path (/). I changed it to a path relative to the root and now just using @csrf.exempt as normal works fine.