Disable WTForms CSRF if access through certain routes

Viewed 176

I'm using Flask-Login, and Flask-WTF for CSRF protection. I want to add some routes for an API. Since request_loader will be used for the API (header token, no cookies), I want to disable CSRF on those routes.

However, there's no difference between users once they are authenticated. There's no way to tell if they were logged in with a cookie with user_loader or with a header with request_loader.

How can I disable CSRF only when the form is used in API routes? Or how can I prevent cookie users from accessing API routes?

1 Answers

Use the form's Meta object, or init meta parameter to control things such as CSRF. For example, if your API is under the api blueprint:

from flask_wtf import FlaskForm

class APIForm(FlaskForm):
    class Meta:
        @property
        def csrf(self):
            return request.blueprint != "api"

class DocumentForm(APIForm):
    ...

# Or for a one-off use:

form = UserForm(meta={"csrf": request.blueprint != "api"})

Or another check, depending on your requirements.


There's no way to tell if they were logged in with a cookie...

You can do anything you want in the callbacks that load users. For example, you could record g.user_from_header = True in your request_loader. Then you could enable the csrf property based on that instead of based on the blueprint. Or add a before_request handler to the API blueprint to abort if it's not set.

@login_manager.request_loader
def user_from_request(request):
    user = ...
    g.user_from_header = True
    return user

@api_bp.before_request
def require_user_from_header():
    if not g.get("user_from_header", False):
        abort(401)
Related