Question

I have created a Django-Rest-Framework API that allows me to successfully run a PUT request via the command line as such:

% curl -X PUT -u myUser:myPassword http://127.0.0.1:3001/api/myEndpoint/64/
{"id": 64, "myAttr1": "Blah1", "myAttr2": "Blah2"}

In my web application, I have the following JQuery AJAX that (as I understand it) should run the exact same command if I'm logged in as myUser:

$.ajax(
    {
        url: "/api/myEndpoint/64/",
        type: "PUT",
        success: function( data ) 
        {
            console.log("Do Something Here");
        }
    }
);

When this .ajax command runs, however, I see the following error in the Chrome Development console:

PUT http://127.0.0.1:3001/api/myEndpoint/64/ 403 (FORBIDDEN) 

After further investigation I also found this Django warning when I ran that .ajax:

WARNING [django.request:99] Forbidden (CSRF token missing or incorrect.): /api/myEndpoint/64/

Why does this work from the command line but not from my web-browser? How do I make this work? I don't fully understand how CSRF stuff works. Would love to get it to just work.

As a reference, here is an excerpt from views.py:

class MyEndPoint(mixins.UpdateModelMixin, generics.GenericAPIView):
    queryset = MyObject.objects.all()
    serializer_class = MyObjectSerializer

    def put(self, request, *args, **kwargs):
        logger.debug("myID = %s" % kwargs["myID"])
        ...

Here is an excerpt from urls.py:

url(r'^api/myEndpoint/(?P<myID>\d+)/?$', views.MyEndPoint.as_view()),
Was it helpful?

Solution

In your command line example you're using -u myUser:myPassword, so you're explicitly authenticating with HTTP Basic authentication.

In the AJAX example you're not doing that, and instead the authentication is implicitly session-based. That means you need to be including a CSRF token.

Take a look at the documentation for how to include CSRF tokens, here and here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top