[Django]-CSRF with Django, React+Redux using Axios

62đź‘Ť

âś…

This Q&A is from 2016, and unsurprisingly I believe things have changed. The answer continues to receive upvotes, so I’m going to add in new information from other answers but leave the original answers as well.

Let me know in the comments which solution works for you.

Option 1. Set the default headers

In the file where you’re importing Axios, set the default headers:

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

Option 2. Add it manually to the Axios call

Let’s say you’ve got the value of the token stored in a variable called csrfToken. Set the headers in your axios call:

// ...
method: 'post',
url: '/api/data',
data: {...},
headers: {"X-CSRFToken": csrfToken},
// ...

Option 3. Setting xsrfHeaderName in the call:

Add this:

// ...
method: 'post',
url: '/api/data',
data: {...},
xsrfHeaderName: "X-CSRFToken",
// ...

Then in your settings.py file, add this line:

CSRF_COOKIE_NAME = "XSRF-TOKEN"

Edit (June 10, 2017): User @yestema says that it works slightly different with Safari[2]

Edit (April 17, 2019): User @GregHolst says that the Safari solution above does not work for him. Instead, he used the above Solution #3 for Safari 12.1 on MacOS Mojave. (from comments)

Edit (February 17, 2019): You might also need to set[3]:

axios.defaults.withCredentials = true

Things I tried that didn’t work: 1

24đź‘Ť

I’ve found out, that axios.defaults.xsrfCookieName = "XCSRF-TOKEN";
and CSRF_COOKIE_NAME = "XCSRF-TOKEN"

DOESN’T WORK IN APPLE Safari on Mac OS

The solution for MAC Safari is easy, just change XCSRF-TOKEN to csrftoken

So, in js-code should be:

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

In settings.py:

    CSRF_COOKIE_NAME = "csrftoken"

15đź‘Ť

This configuration works for me without problems Config axios CSRF django

import axios from 'axios'

/**
 * Config global for axios/django
 */
axios.defaults.xsrfHeaderName = "X-CSRFToken"
axios.defaults.xsrfCookieName = 'csrftoken'

export default axios

8đź‘Ť

After spending too many hours researching, and implementing the above answer, I found my error for this problem! I have added this answer to be supplemental of the accepted answer. I had set up everything as mentioned, but the gotcha for me was actually in the browser itself!

If testing locally, make sure you are accessing react through 127.0.0.1 instead of localhost! localhost handles request headers differently and doesn’t show the CSRF tokens in the header response, where as 127.0.0.1 will! So instead of localhost:3000 try 127.0.0.1:3000!

Hope this helps.

5đź‘Ť

The “easy way” almost worked for me. This seems to work:

import axios from 'axios';
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "XCSRF-TOKEN";

And in the settings.py file:

CSRF_COOKIE_NAME = "XCSRF-TOKEN"

2đź‘Ť

You could add the Django-provided CSRF token manually into all of your post requests, but that’s annoying.

From the Django docs:

While the above method (manually setting CSRF token) can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many JavaScript frameworks provide hooks that allow headers to be set on every request.

The docs have code you can use to pull the CSRF token from the CSRF token cookie and then add it to the header of your AJAX request.

2đź‘Ť

There is actually a really easy way to do this.

Add axios.defaults.xsrfHeaderName = "X-CSRFToken"; to your app config and then set CSRF_COOKIE_NAME = "XSRF-TOKEN" in your settings.py file. Works like a charm.

1đź‘Ť

For me, django wasn’t listening to the headers that I was sending. I could curl into the api but couldn’t access it with axios. Check out the cors-headers package… it might be your new best friend.

I fixed it by installing django-cors-headers

pip install django-cors-headers

And then adding

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

and

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

into my settings.py

I also had

ALLOWED_HOSTS = ['*']
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_EXPOSE_HEADERS = (
    'Access-Control-Allow-Origin: *',
)

in my settings.py although that is probably overkill

1đź‘Ť

In addition to what yestema said (and echoed by krescruz, cran_man, Dave Merwin et. al), You also need:

axios.defaults.withCredentials = true

Leave a comment