4

In my cenario I am using a form in my react frontend (http://localhost:3000/submit) to post to my url http://localhost:8000/api/submit/

However, I have received this response:

"detail": "CSRF Failed: CSRF token missing or incorrect."

My class view is something like that:

from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser

class Submit(APIView):
    parser_classes = (MultiPartParser, FormParser)
    def post(self, request, *args, **kwargs):
        #custom post

I have two questions:

  1. How do I decorate dispatch() to exempt csrf?
  2. How can I provide CSRF to my frontend?

**

SOLUTION by Risadinha:

**

import cookie from "react-cookies";

...

<input
 type="hidden"
 value={cookie.load("csrftoken")}
 name="csrfmiddlewaretoken"
/>
2
  • Have you taken a look at using TokenAuthentication: django-rest-framework.org/api-guide/authentication/… -- TokenAuthentication might be more appropriate for your client-server set up. Commented Sep 26, 2018 at 13:56
  • I did, but I want to learn how to make it work with CSRF. Commented Sep 26, 2018 at 15:08

2 Answers 2

3

You need to set both the cookie and the header to the CSRF token as transmitted during the initial call wich loads the react page.

Basically you need to read the value of the cookie "csrftoken" as transmitted from the Django server and set that as the value of the header "X-CSRFTOKEN" for all the post AJAX requests in your react app. Best done generally (index.js for example).

Example using axios (we are using graphql) client in React:

import axios from "axios";
import cookie from "react-cookies";

axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";

your_client.setHeaders({"X-CSRFTOKEN": cookie.load("csrftoken")});

Without ajax, add the cookie's value to the form like this - if you cannot use the template tag {% csrf_token %} (in a react form):

<input type="hidden" name="csrfmiddlewaretoken" value="{value-of-the-cookie}" /> 

The documentation: https://docs.djangoproject.com/en/3.1/ref/csrf/

Sign up to request clarification or add additional context in comments.

3 Comments

Where should I put those codes? And what is "your_client"?
It depends on how you implement the AJAX requests in your react app. We are using axios and therefore we have a client instance. As this is somthing that should be applied to all ajax (post) requests it would be practical to set this up in a general part of the code like index.js.
but in this case I am not using AJAX. I have a form and post the input data directly to my django back end. I do not know how to generate a CSRF token to insert into a <input type="hidden"/> or how to retrieve it from django and set the input value to it.
0

This seems a bit hacky but you can get the csrf token in a view with the django.middleware.csrf.get_token() method. So I would make a view like this:

from django.http import JsonResponse

def get_csrf(request):
    csrf_token = django.middleware.csrf.get_token()
    return JsonResponse({'csrf_token':csrf_token})

Of course you want to protect this request so anyone can't grab the token. Which seems to defeat the purpose of it anyway...

2 Comments

Any request that is not CSRF exempt already contains the token in the header as well as in the cookie. It does not make any sense to issue yet another request to get data that has already been included twice.
I think this can help someone who uses something like create-react-app and the front-end is hosted separate to the backend because they can use django sessions to store user data if request they make contains the token

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.