Non-GET Requests Returning 403 Error in Django Web Project

sccotliu

Sccotliu

Posted on December 14, 2023

Non-GET Requests Returning 403 Error in Django Web Project

During the development of a web project based on Django, I encountered a strange issue: all non-GET requests such as POST, PATCH, and DELETE that were previously working fine started returning a 403 error.

Here are the basic details:

Django==4.0.10
djangorestframework==3.13.1
my restframework configuration in settings.py
Enter fullscreen mode Exit fullscreen mode
REST_FRAMEWORK = {
    # "DEFAULT_PAGINATION_CLASS": "utility.rest_framework.paginations.Pagination",
    # "DEFAULT_PAGINATION_CLASS": "utility.rest_framework.paginations.PageNumberPaginationWithoutCount",
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
    "PAGE_SIZE": 20,
    "DEFAULT_RENDERER_CLASSES": [
        # "rest_framework.renderers.JSONRenderer",
        "utility.rest_framework.renderers.CustomJSONRender",
        "rest_framework.renderers.BrowsableAPIRenderer",
    ],
    "DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.BasicAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
}
Enter fullscreen mode Exit fullscreen mode

My API views are based on either ModelViewSet or APIView. The endpoints were working correctly in the morning, but after fixing a few performance-related issues, all non-GET requests started returning a 403 error. I checked the middleware and the restframework configuration in settings, but didn't find any apparent issues.

While debugging the code, I discovered a method in the rest_framework.views module's APIView class with the following code:

def perform_authentication(self, request):
    """
    Perform authentication on the incoming request.

    Note that if you override this and simply 'pass', then authentication
    will instead be performed lazily, the first time either
      request.user   or   request.auth   is accessed.
    """
    request.user
Enter fullscreen mode Exit fullscreen mode

Every time I stepped into this method, the program would exit and raise a 403 error.

To resolve the issue, I tried a workaround by manually extracting the CSRF token from the cookie and adding it to the request header. This workaround solved the problem, so I created a BaseAPIView class and made all views inherit from it.

However, I'm still unsure about the root cause of the problem, which is quite frustrating.

The possible cause could be Django's CSRF protection mechanism, which requires including the CSRF token in every non-GET request. It's possible that in the morning, the CSRF token was automatically included somewhere, but the changes made later caused the CSRF token to be missing.

My solution of manually extracting the CSRF token from the cookie and adding it to the request header bypasses Django's CSRF protection mechanism. However, this approach is not recommended as it may introduce security vulnerabilities.

I would appreciate your help in understanding the reason behind this issue.

💖 💪 🙅 🚩
sccotliu
Sccotliu

Posted on December 14, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related