Search code examples
djangodjango-rest-frameworkcsrf

CSRF cookie error after Django 3.2 update (DRF with token authentication)


I was looking to update my app backend from Django 3.1.14 (working fine but no longer supported) to a newer version (I tried both 3.2 and 4.0), but after updating I started getting a CSRF cookie error.

Forbidden (CSRF cookie not set.): /api-token-auth/

Does anybody by any chance know what's changed in Django in regard to CSRF, and how to avoid the errors?

I was under the impression that CSRF is not enforced when using Django Rest Framework with token authentication. I tried anyway to remove the 'django.middleware.csrf.CsrfViewMiddleware' middleware, to add @csrf_exempt to all the views, deleted all existing tokens and logged out of Django admin, but to no avail. My DRF configuration in settings.py is as follows:

INSTALLED_APPS = [
    'rest_framework',
    'rest_framework.authtoken',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

Edit: my own answer below


Solution

  • The urlpatterns order in urls.py was the problem. This answer helped.

    If the Django admin url is above the api urls, any api request will not even reach these apis and Django will throw the CSRF cookie error.

    Working in Django 3.1, but not working in Django 3.2:

    urlpatterns = [
        path('', admin.site.urls),
        url(r'^api-token-auth/', views.MyLoginToken.as_view()),
        url(r'^', include('myapp.backend.urls')),
    ]
    

    Working in Django 3.2:

    urlpatterns = [
        url(r'^', include('myapp.backend.urls')),  # move CSRF exempt apis to the top
        url(r'^api-token-auth/', views.MyLoginToken.as_view()),
        path('', admin.site.urls),  # move CSRF protected endpoints to the end
    ]
    

    I couldn't find any documentation for this breaking change from Django 3.1 to Django 3.2.