pallets-eco / flask-wtf

Simple integration of Flask and WTForms, including CSRF, file upload and Recaptcha integration.
https://flask-wtf.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.47k stars 308 forks source link

Allow disabling CSRF based on request context #495

Open hMED22 opened 2 years ago

hMED22 commented 2 years ago

Instead of CSRFProtect.exempt that disables CSRF on a view for all requests, there should also be a way to disable it for all views based on the request context, like token authenticated requests for example.

For this the docs suggest

setting WTF_CSRF_CHECK_DEFAULT to False, and selectively call protect() only when you need.

But it doesn't feel right to disable the extension globally, plus that way CSRFProtect.exempt is no longer usable.

I tried something like

@app.before_request
def _disable_csrf_for_token_auth():
    if token_authenticated(request):
        g.csrf_valid = True

But CSRF protection runs and returns an error response before my hook gets called.

I am now going with a subclass:

class AuthAwareCSRFProtect(CSRFProtect):
    def protect(self):
        if token_authenticated(request):
            g.csrf_valid = True
            return

        return super().protect()

One problem of this is that g.csrf_valid is internal to flask-wtf and not documented as part of the API so I don't know if it's a good idea to use it.

fiendish commented 6 months ago

I also desire to transiently disable CSRF for a single request based on the request context.

One problem of this is that g.csrf_valid is internal to flask-wtf and not documented as part of the API so I don't know if it's a good idea to use it.

Likewise. An ok fix for this could be to just call it official and document it.