0

I'm trying to post data from a form built in React over a Django-Rest-Framework API and have run into an issue with the authentication. I can post fine if I turn off authentication on the API View, so I think I've narrowed it down to how I'm passing the data in the form.

My DRF view looks like this:

class PropertyListCreate(generics.ListCreateAPIView):
    authentication_classes = (SessionAuthentication,)
    permission_classes = (IsAuthenticated,)

    queryset = models.Property.objects.all()
    serializer_class = serializers.PropertySerializer

The handler for the Submit is below.

handleSubmit = e => {
    e.preventDefault();
    const { name, type, address, city, state, zip_code } = this.state;
    const property = { name, type, address, city, state, zip_code };
    const conf = {
        credentials: 'include',
        method: 'POST',
        body: JSON.stringify(property),
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'X-CSRFToken': cookie.load('csrftoken')
         }
    };
    fetch(this.props.endpoint, conf).then(response =>
        console.log(response),
        console.log(conf)
        );
};

When I attempt to post with the above code, I get a 400 Error - and if I remove the 'X-CSRFToken': cookie.load('csrftoken'), I get a 403 Error (Forbidden). My understanding of a 400 Error is that the request was badly formatted, so I'm thinking that I'm sending the csrf token incorrectly?

This is the output from console.log(response):

Response {type: "basic", url: "http://127.0.0.1:8000/api/properties/", 
redirected: false, status: 400, ok: false, …}

The response after removing the X-CSRFToken from the headers:

Response {type: "basic", url: "http://127.0.0.1:8000/api/properties/", 
redirected: false, status: 403, ok: false, …}
jeff m
  • 265
  • 8
  • 24
  • can you log `JSON.stringify(property)` and `cookie.load('csrftoken')`? To see what kind of data you're sending. – King Reload Apr 09 '18 at 09:21
  • both outputting what I expect: JSON.stringify(property) -> {"name":"Shopping Mall","type":"","address":"100 Lane Street","city":"Baltimore","state":"Maryland","zip_code":"21201"} cookie.load('csrftoken') -> 3Bo5oT9rcV5ULb4ZIuBVCO4m0INAifzyb6TX9TgTYi6ka9ZD56rFevo6mdrHBF6b – jeff m Apr 09 '18 at 09:24
  • it's neither of those that cause the problem. they are both correctly formatted and the csrf token is sent as `header`, meaning as well that it's not the csrf token. – King Reload Apr 09 '18 at 09:28
  • What do you have for `CSRF_*`/`SESSION_*` in `settings.py`? – Alasdair Apr 09 '18 at 09:30
  • What's the response body when you get a 400 ? – Linovia Apr 09 '18 at 09:41
  • I think you actually need to set `'X-Requested-With': 'XMLHttpRequest'` as header as well. Reading the reason on this post: https://stackoverflow.com/a/22533680/7707749 – King Reload Apr 09 '18 at 09:41
  • @Alasdair There is nothing in settings.py set for those. Should there be? – jeff m Apr 09 '18 at 09:44
  • @Linovia response.body is ReadableStream – jeff m Apr 09 '18 at 09:49
  • I asked because some settings like [`CSRF_COOKIE_HTTPONLY`](https://docs.djangoproject.com/en/2.0/ref/settings/#csrf-cookie-httponly) or [`CSRF_HEADER_NAME`](https://docs.djangoproject.com/en/2.0/ref/settings/#csrf-header-name`) could cause problems. As far as I know you should be OK with the defaults. – Alasdair Apr 09 '18 at 09:50
  • @KingReload No luck with adding that, still getting a 400. The reason I think the csrf token is the problem is that I'm getting a 403 (Post is going through) without setting X-CSRFToken, but I get a 400 (Invalid Syntax) when I include X-CSRFToken. – jeff m Apr 09 '18 at 09:52
  • @jeffm it's not supposed to fix the problem, it's supposed to make `csrf` attacks harder. And the 403 error is because the request is forbidden. The csrf token grants you access to post. Maybe you're forgetting to post it to a certain `url`? Does the django view register that the post is going through? – King Reload Apr 09 '18 at 09:55
  • @jeffm that's not the content – Linovia Apr 09 '18 at 10:05
  • @Linovia there is a locked: false and __proto__ – jeff m Apr 09 '18 at 10:15

0 Answers0