Search code examples
djangoaxioshttp-status-code-403

Axios PUT Request 403 Forbidden when logged into Django


Whenever I am logged into a django user and I try and send a PUT request to my URL I get a 403 Forbidden Error. However, it works both when I am not logged in and also from the Django Rest API client.

Here is my code in my frontend:

let parameters = `user/${userID}/`
    return new Promise((resolve, reject) => {
        axios({
            method: 'PUT',
            url: 'http://127.0.0.1:8000/' + parameters,
            data: updatedUser,
            headers: {
                'Content-Type': 'application/json',
            },
        })
            .then((response) => {
                resolve(response)
            })
            .catch(error => {
                console.log(error)
                // reject(error)
            })
    });

I am very confused as I can't see the difference when I am logged into a django user and when I am not, as nothing changes in the frontend. Thanks

EDIT: This is in my urls.py

 path('user/<id>/', views.RetrieveUpdateDestroyUser.as_view()),

And this is the view:

class RetrieveUpdateDestroyUser(RetrieveUpdateDestroyAPIView):
"""
View to handle the retrieving, updating and destroying of a User.
This View will also log any changes made to the model.
"""
serializer_class = UserCreateUpdateSerializer
queryset = CustomUser.objects.all()
lookup_field = 'id'
permission_classes = (AllowAny,)

def update(self, request, *args, **kwargs):
    """
    PUT and UPDATE requests handled by this method.
    """
    return super().update(request, *args, **kwargs)

I have also tested doing POST and PUT when I am logged into a user and they don't work, but GET does. Thanks

Also tried disabled CSRF but to no avail either


Solution

  • Writing this answer to summarize what we have discovered.

    The problem: the AJAX (PUT) call to the DRF endpoint fails with 403 HTTP error for authenticated users and works just fine for anonymous users

    Desired Behaviour: make that call working for both anonymous and authenticated users

    Reason: by default DRF perform CSRF check for unsafe HTTP methods (POST, PUT, PATCH and DELETE) https://www.django-rest-framework.org/topics/ajax-csrf-cors/

    Possible Solutions:

    1. Disable CSRF check like described here https://stackoverflow.com/a/30875830/764182
    2. Pass CSRF token within the PUT request. For more information about CSRF + AJAX in Django read here https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax. For Axios and default Django settings the solution might be:
    axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
    axios.defaults.xsrfCookieName = "csrftoken";
    axios.defaults.withCredentials = true;