Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-Restful POST fails due CSRF protection of Flask-WTF

I am using normal flask web + flask-restful. So I need CSRF protection for web but not for REST.

The moment I enable CsrfProtect(app) of flask-wtf, all my post unit tests for flask-restful return a 400.

Is there a way to disable CSRF protection for REST services since they are coming from mobile handsets without session handling anyway, hence CSRF wouldn't make much sense.

This is how I test it:

rv = self.client.post('api/v1.0/verify-email', environ_base={'REMOTE_ADDR': '127.0.0.1'}, headers={'Content-Type':'application/json'}, data=json.dumps(data))
self.check_content_type(rv.headers)
eq_(rv.status_code, 412)
like image 268
Houman Avatar asked Feb 02 '14 10:02

Houman


2 Answers

You can use the @csrf.exempt decorator, which you need to add directly on the API object, with the decorators argument; this would apply the decorator to all API routes:

csrf_protect = CsrfProtect(app)
api = restful.Api(app, decorators=[csrf_protect.exempt])

You cannot use resource method decorators as they are not the final view functions that the exempt decorator requires to work.

It appears you cannot protect individual resources and exempt others; this is a limitation in the method used by Flask-Wtf's method of recording what views are exempted.

like image 157
Martijn Pieters Avatar answered Sep 20 '22 19:09

Martijn Pieters


More simple solution (related commit):

csrf.exempt(api_blueprint)

And here is a complete demo:

from flask import Flask, Blueprint
from flask_wtf import CSRFProtect

app = Flask(__name__)
csrf = CSRFprotect(app)

api_blueprint = Blueprint('api', __name__)
csrf.exempt(api_blueprint)

app.register_blueprint(api_blueprint)
like image 44
Grey Li Avatar answered Sep 20 '22 19:09

Grey Li