How to disable csrf for a view with flask-wft for a restapi?

Question:

I get problem for disable csrf using flask-wtf for a restapi. The problem is similar like here: Flask-Restful POST fails due CSRF protection of Flask-WTF, but I use flask original instead of flask-restful.

I use the @csrf.exemptdecorator, and I did exactly like the documentation, but still can not disable the csrf. Here is my code, do you know what is the problem?

myApp.py

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)    
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = "secret"

db = SQLAlchemy(app)

csrf = CSRFProtect(app) # initialize the csrf protect

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String())

class myForm(FlaskForm):
    username = StringField("user name")

@app.route("/check", methods=['POST'])    
@csrf.exempt # why this code doesn't work???!!! :(
def check():
    form = myForm(request.form)

    if form.validate():
        user = User(username=form.username.data)
        db.session.add(user)
        db.session.commit()
        return jsonify(message="user saved!"), 200
    else:
        return jsonify(message=form.errors), 404

if __name__ == '__main__':
    app.run(debug=True)

My Postman always return:

{
    "message": {
        "csrf_token": [
            "The CSRF token is missing."
        ]
    }
}
Asked By: xirururu

||

Answers:

FlaskForm.validate() seems to be the one returning that error, i.e. try

form = myForm(request.form, csrf_enabled=False)

or

class myForm(FlaskForm):
    class Meta:
        csrf = False

     username = StringField("user name")

since csrf_enabled seems to be deprecated.

From the documentation

Any view using FlaskForm to process the request is already getting CSRF protection.

Answered By: J.J. Hakala

You can pass meta={‘csrf’: False} as parameter in your constructor

form = myForm(request.form, meta={'csrf': False})

You can also pass the route[s] you would like to exclude to csrf as a string:

csrf = CSRFProtect(app)
csrf.exempt('app.blueprints.views.my_view_fn')
Answered By: nikk wong