How to use csrf_token in Django RESTful API and React?

Question:

I have previous experience in Django. If add line {csrf_token} in Django templates then Django handles the functionalities of csrf_token. But when I am trying to develop an API using Django REST Framework then I get stuck. How can I add and handle functionalities like csrf_token in API (back end, developed using Django REST Framework) and React Native/React JS (front end) like Django templates?

Asked By: Taohidul Islam

||

Answers:

I used jquery for ajax in react, so in this case here is a solution :

let csrfcookie = function() {  // for django csrf protection
            let cookieValue = null,
                name = "csrftoken";
            if (document.cookie && document.cookie !== "") {
                let cookies = document.cookie.split(";");
                for (let i = 0; i < cookies.length; i++) {
                    let cookie = cookies[i].trim();
                    if (cookie.substring(0, name.length + 1) == (name + "=")) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
};

$.ajax({
       type: "POST",
       beforeSend: function(request, settings) {
                    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                        request.setRequestHeader("X-CSRFToken", csrfcookie());
                    }
},

.... /// other codes
Answered By: pyprism

The first step is to get CSRF token which can be retrieved from the Django csrftoken cookie.

Now from the Django docs you can find out how to get the csrf token from the cookie by using this simple JavaScript function:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

Now, you can retrieve the CSRF token by calling the getCookie('csrftoken') function

var csrftoken = getCookie('csrftoken');

Next you can use this csrf token when sending a request with fetch() by assigning the retrieved token to the X-CSRFToken header.

  fetch(url, {
    credentials: 'include',
    method: 'POST',
    mode: 'same-origin',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-CSRFToken': csrftoken
    },
    body: {}
   })
  }

Rendering the CSRF Token in React Forms:

If you are using React to render forms instead of Django templates you also need to render the csrf token because the Django tag { % csrf_token % } is not available at the client side so you need to create a higher order component that retrieves the token using the getCookie() function and render it in any form.

Lets add some line in csrftoken.js file.

import React from 'react';

var csrftoken = getCookie('csrftoken');

const CSRFToken = () => {
    return (
        <input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />
    );
};
export default CSRFToken;

Then you can simply import it and call it inside your form

import React, { Component , PropTypes} from 'react';

import CSRFToken from './csrftoken';


class aForm extends Component {
    render() {

        return (
                 <form action="/endpoint" method="post">
                        <CSRFToken />
                        <button type="submit">Send</button>
                 </form>
        );
    }
}

export default aForm;

The Django CSRF Cookie

React renders components dynamically that’s why Django might not be able to set a CSRF token cookie if you are rendering your form with React. This how Django docs says about that:

If your view is not rendering a template containing the csrftoken
template tag, Django might not set the CSRF token cookie. This is
common in cases where forms are dynamically added to the page. To
address this case, Django provides a view decorator which forces
setting of the cookie: ensurecsrf_cookie().

To solve this issue Django provides the ensurecsrfcookie decorator that you need to add to your view function. For example:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def myview(request):
Answered By: orvi

You can handle CSRF token protection in your Django RESTful API and React application by using the django-react-csrftoken library. This library simplifies the process of including CSRF tokens in your React forms and communicating securely with your Django backend.

You can install django-react-csrftoken in your React project using npm:

npm install --save django-react-csrftoken

In your React component, you can use the DjangoCSRFToken component to include the CSRF token within your form:

import React from 'react';
import DjangoCSRFToken from 'django-react-csrftoken';

class MyLoginForm extends React.Component {
  render() {
    return (
      <div className="container">
        <form>
          <DjangoCSRFToken /> {/* Include the CSRF token */}
          {/* Other form fields (e.g., email, password) */}
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

To ensure that the CSRF token is set in the response cookies for views that render forms in Django, you can use the @ensure_csrf_cookie decorator:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def register_view(request):
    # Your view logic here

For more detailed information and examples, you can refer to the official django-react-csrftoken GitHub repository. The repository’s README provides comprehensive documentation on how to use the library effectively.

Answered By: Abhijith Subash