What is CSRF?
How to protect against CSRF with Django Ninja
Use an authentication method not automatically embedded in the request
CSRF attacks rely on authentication methods that are automatically included in requests started from another site, like cookies or Basic access authentication.
Using an authentication method that does not automatically gets embedded, such as the
Authorization: Bearer header for exemple, mitigates this attack.
Use Django's built-in CSRF protection
By default, Django Ninja has CSRF protection turned OFF for all operations.
To turn it on you need to use the
csrf argument of the NinjaAPI class:
from ninja import NinjaAPI api = NinjaAPI(csrf=True)
Warning: It is not secure to use API's with cookie-based authentication! (like
django_auth) when csrf is turned OFF.
Django Ninja will automatically enable csrf for Cookie based authentication
from ninja import NinjaAPI from ninja.security import APIKeyCookie class CookieAuth(APIKeyCookie): def authenticate(self, request, key): return key == "test" api = NinjaAPI(auth=CookieAuth())
or django-auth based (which is inherited from cookie based auth):
from ninja import NinjaAPI from ninja.security import django_auth api = NinjaAPI(auth=django_auth)
You can use the Django ensure_csrf_cookie decorator on an unprotected route to make it include a
Set-Cookie header for the CSRF token. Note that:
- The route decorator must be executed before (i.e. above) the ensure_csrf_cookie decorator).
- You must
csrf_exempt that route.
ensure_csrf_cookie decorator works only on a Django
HttpResponse and not also on a dict like most Django Ninja decorators.
from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie @api.post("/csrf") @ensure_csrf_cookie @csrf_exempt def get_csrf_token(request): return HttpResponse()
Set-Cookieheader from Django.
You may use the Using CSRF protection with AJAX and Setting the token on the AJAX request part of the How to use Django’s CSRF protection to know how to handle that CSRF protection token in your frontend code.
A word about CORS
You may want to set-up your frontend and API on different sites (in that case, you may check django-cors-headers). While not directly related to CSRF, CORS (Cross-Origin Resource Sharing) may help in case you are defining the CSRF cookie on another site than the frontend consuming it, as this is not allowed by default by the Same-origin policy. You may check the django-cors-headers README then.