Angular2 and Django: CSRF Token Headache
<p><strong>The Issue I'm Having</strong></p>

<ul>
<li>I'm making an Ajax POST request from my <strong>Angular2</strong> client to my <strong>Django</strong> (v1.9) backend (both on localhost, different ports). I'm not yet using the Django REST framework, I'm just dumping the JSON in Django without any add-ons.</li>
<li>I have been issued a <strong>csrf token</strong> by the server, and I'm manually sending it back in the HTTP headers (I can see it there when I make the call). </li>
<li>However, I still get the error from django: <strong>Forbidden (CSRF cookie not set.)</strong></li>
<li>I've read a number of other threads, and tried a few things, but still can't get Django to accept the CSRF token.</li>
</ul>

<p><strong>Client side code:</strong></p>

<pre><code>private _editUserUri = "http://127.0.0.1:8000/search/edit/user/";

constructor(private _http: Http){}

getCookie(name) {
    let value = "; " + document.cookie;
    let parts = value.split("; " + name + "=");
    if (parts.length == 2) 
      return parts.pop().split(";").shift();
}

validateData(userdata) {
    return true;
}

editUser(userdata) {

    console.log("UserService: createUser function called");
    console.log(JSON.stringify(userdata));

    if(this.validateData(userdata)) {

        let headers = new Headers({
            'Content-Type': 'application/json',
            'X-CSRFToken': this.getCookie('csrftoken')
        });

        let options = new RequestOptions({ headers: headers });

        return this._http
            .post(
                this._editUserUri,
                JSON.stringify(userdata),
                options)
            .map(res =&gt; {
                console.log(res.json());
                return res.json();
            })
    }

}
</code></pre>

<p><strong>Screenshot of csrf token in header (x-csrftoken). This is exactly how Django expects it</strong> (<a href="https://docs.djangoproject.com/en/1.9/ref/csrf/" rel="nofollow">source</a>)
<a href="http://i.stack.imgur.com/sAFUD.png" rel="nofollow"><img src="http://i.stack.imgur.com/sAFUD.png" alt="Screenshot"></a></p>

<p><strong>What I've tried / considered</strong></p>

<ul>
<li><p>I thought that perhaps the csrf token is out of date. I've tried to generate a new one, but I haven't yet managed to get Django to issue me a new one. I've tried using the @ensure_csrf_cookie decorator, but still nothing. If I have a csrf token in a cookie which was placed this morning, would I expect it to be replaced by a new, up-to-date version?</p></li>
<li><p>Another thought was that the header name (x-csrftoken) is in lower case. Django specifies that the header name should be the following: <strong>X-CSRFToken</strong>. However, from reading online it seems that headers should generally be case sensitive. In any case, Angular2 is automatically converting the header name to lower case.</p></li>
<li><p>I tried some other solutions I found on Stack Overflow (<a href="http://stackoverflow.com/questions/34494876/what-is-the-right-way-to-use-angular2-http-requests-with-django-csrf-protection">example</a>) but had no luck.</p></li>
<li><p>I thought that maybe this was related to CORS, but the first OPTIONS request returns a 200 from my Django server. This pre-flight request wouldn't need to include the csrf token in its headers also, would it? (excuse my ignorance)</p></li>
<li><p>I'm pretty sure my settings are fine. I have 'django.middleware.csrf.CsrfViewMiddleware' in MIDDLEWARE_CLASSES, <strong>CSRF_COOKIE_SECURE = False</strong>, <strong>CORS_ALLOW_CREDENTIALS = True</strong> and <strong>CORS_ORIGIN_ALLOW_ALL = True</strong></p></li>
</ul>

<p>If anyone could help I'd greatly appreciate it!</p>

<p>Nick</p>

<p>I think the problem is that your request only has the CSRF token header, but not the cookie (see the <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Double_Submit_Cookie" rel="nofollow">double submit</a> mitigation against CSRF, the header you're sending should be compared to the cookie).</p>

<p>I don't quite understand what exactly is happening though. If you elaborate a bit more on where the Angular app is downloaded from and how it gets the CSRF cookie from Django, which is a different origin, I can probably edit this answer to help more. What I don't get is that if the Angular app is downloaded from port A, from where does it have a CSRF cookie for Django on port B.</p>

<p><strong>Edit:</strong></p>

<p>Ah you're using CORS. I think you need <code>withCredentials</code> in the jQuery request so that the csrf cookie is sent with the request:</p>

<pre><code>xhrFields: {
    withCredentials: true
}
</code></pre>

<p>Django then needs to send <code>Access-Control-Allow-Credentials: true</code> I think.</p>

python django angular2 cors csrf