Forbidden (CSRF token missing or incorrect.) how to send CSRF token from frontend to backend?

Viewed 31

I have a Django project, where I need to send a date string from frontend to backend. At frontend I am using the javascript fetch method

async function getCustomerInDeliveryDate(deliveryDate : String) {
    const response = await fetch('getCustomerInTripDate', {
        method : 'POST',
        headers : {
            'Content-Type' : 'application/json',
        },
        body: JSON.stringify({
            deliveryDate :  deliveryDate
        }),
    });
    return response
}

From Django backend I currently implemented a simple method that returns a string back to frontend

class GetCustomerInTripDate(LoginRequiredMixin, View):
    def post(self, request, *args, **kwargs):
        print('Backend received call from front end!!!!!!!!!!!!!')
        return JsonResponse({'data': ['hello', 'world']}, status = 200)

The error that I receive when I try to send to backend is

Forbidden (CSRF token missing or incorrect.): /staff/getCustomerInTripDate

I am not sure how to send the csrf token. The research I have done so far all indicated that credentials should be set as "same-origin", and I have tried it but still get the same error.

3 Answers

You just need to add {% csrf_token %} into the template.

If you are using a normal HTML form, place it inside the form.

<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>

If you are using Ajax it doesn't matter where you place it you just have to add it to the POST data

submitData = {
  
  // other data

  'csrfmiddlewaretoken': $("[name=csrfmiddlewaretoken]").val()
};

$.ajax({
  method: 'post',
  url: 'some_url',
  data: submitData,
  success: function(data){
    // do things
  },
  error: function(event,xhr,settings,errorText){
    // do error things
  }
});

The error you are getting is Cross Site Request Forgery( CSRF )

You have detailed explanation here https://docs.djangoproject.com/en/4.1/ref/csrf/

Long story short, try adding {% csrf_token %} protection in django templates.

<form action="" method="post">
    {% csrf_token %} <----- ADD THIS
......everything else goes here
</form>

Or if you dont use django templates try adding csrf decorator to your view. I think it should be something like this:

from django.utils.decorators import method_decorator<----- ADD THIS
    
@method_decorator(csrf_exempt, name='dispatch')<----- ADD THIS
class GetCustomerInTripDate(LoginRequiredMixin, View):
    def post(self, request, *args, **kwargs):
        print('Backend received call from front end!!!!!!!!!!!!!')
        return JsonResponse({'data': ['hello', 'world']}, status = 200)

I think this should work, hope it helps. Best regards.

The CSRF token is by default stored as a cookie. So you should retrieve the cookie with javascript, then send the token it.

Or you could make a restful endpoint.

Related