2

I am struggling with 403/CSRF issues when trying to use Angular 2 to POST to my Django server.

Both my server code and my Angular code are running on the same 127.0.0.1 server.

When the Angular code is run the server returns a 403 4612 error

My Django View code looks like this (I am using the Django REST Framework):

rom django.utils import timezone
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.models import User
from .models import Item, Seen, Keyword, Flag
from django.utils.decorators import classonlymethod
from django.views.decorators.csrf import csrf_exempt
from rest_framework import viewsets
from items.serializers import ItemSerializer, UserSerializer
from rest_framework.authentication import SessionAuthentication

class CsrfExemptSessionAuthentication(SessionAuthentication):
    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening


class ItemViewSet(viewsets.ModelViewSet):
    queryset = Item.objects.all().order_by('-date_added')
    serializer_class = ItemSerializer
    authentication_classes = (CsrfExemptSessionAuthentication, )
    #permission_classes = [IsAccountAdminOrReadOnly]

    """
        Use the API call query params to determing what to return

        API params can be:

        ?user=<users_id>&num=<num_of_items_to_return>&from=<user_id_of_items_to_show>
    """

    def get_queryset(self):
        this_user = self.request.query_params.get('user', None)
        restrict_to_items_from_user_id = self.request.query_params.get('from', None)
        quantity = self.request.query_params.get('num', 20)

        if restrict_to_items_from_user_id is not None:
            
            queryset = Item.objects.filter(owner=restrict_to_items_from_user_id, active=True).order_by('-date_added')[0:int(quantity)]
        elif this_user is not None:
            
            queryset = Item.objects.filter(active=True, credits_left__gt=0).exclude(pk__in=Seen.objects.filter(user_id=this_user).values_list('item_id', flat=True))[0:int(quantity)]
        else:
            
            queryset = Item.objects.filter(active=True, credits_left__gt=0)[0:int(quantity)]

        return queryset

My Angular 2 code that does the POST looks like this:

import {Injectable, Inject} from 'angular2/core';
import {Http, Headers, HTTP_PROVIDERS} from 'angular2/http';
import {UserData} from './user-data';
import 'rxjs/add/operator/map';


@Injectable()
export class ConferenceData {
  static get parameters(){
    return [[Http], [UserData]];
  }

  constructor(http, user) {
    // inject the Http provider and set to this instance
    this.http = http;
    this.user = user;
  }

  load() {

    // Example of a PUT item
    let body = JSON.stringify({ url: 'fred', item_type: 'P', owner_id: 2 });

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');

    this.http.post('http://127.0.0.1:8000/api/items/', body, {
        headers: headers
      })
      .subscribe(
        data => {
          alert(JSON.stringify(data));
        },
        err => this.logError(err.json().message),
        () => console.log('Authentication Complete')
      );
  }
}

I find CSRF issues really difficult to get to grips with!

EDIT: Added CORS settings

My CORS settings look like this:

CORS_ORIGIN_ALLOW_ALL = True    
CORS_ORIGIN_WHITELIST = (
    'veeu.co',
    '127.0.0.1'
)
CORS_ORIGIN_REGEX_WHITELIST = ()
CORS_URLS_REGEX = '^.*$'
CORS_ALLOW_METHODS = (
    'GET',
    'POST',
    'PUT',
    'PATCH',
    'DELETE',
    'UPDATE',
    'OPTIONS'
)
CORS_ALLOW_HEADERS = (
    'x-requested-with',
    'content-type',
    'accept',
    'origin',
    'authorization',
    'x-csrftoken'
)
CORS_EXPOSE_HEADERS = ()
CORS_ALLOW_CREDENTIALS = False
Bill Noble
  • 6,466
  • 19
  • 74
  • 133
  • You need to include the CSRF token in the header. Here is a link to a similar issue http://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf. – Pieter Hamman Apr 01 '16 at 17:14
  • Yes it was that link that I got my CsrfExemptSessionAuthentication code from but it doesn't appear to work. – Bill Noble Apr 01 '16 at 17:58

1 Answers1

1

Rather than disabling the CSRF protection, you can add the token as a header to your ajax requests. See the docs, in particular the last section for AngularJS.

You might have to use csrf_ensure for the initial Django view, to ensure that Django sets the csrf cookie.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Thanks Alasdair but I need an Angular 2 solution. – Bill Noble Apr 01 '16 at 17:05
  • [This question](http://stackoverflow.com/questions/34494876/what-is-the-right-way-to-use-angular2-http-requests-with-django-csrf-protection) might help – Alasdair Apr 01 '16 at 19:05
  • I have tried that link but the code doesn't work for me unfortunately. I need to work out how to to get the cookie from Django into my app. – Bill Noble Apr 01 '16 at 19:18