2

My basic goal is to send some data from a chrome plugin to a Django server. My basic attempt thus far has looked like this:

  1. Use javascript to capture data within plugin code.

    loginData = {
        'username': document.getElementById("login-email").value,
        'password': document.getElementById("login-password").value
    };
    
  2. Send this to Django using the REST Framework.

    csrfToken = getCookie('csrftoken');
    
    $.ajax(login_url, {
        type: 'post',
        data: JSON.stringify(loginData),
        contentType: 'application/JSON',
        dataType: 'json',
        headers: {
            'HTTP_X_CSRFTOKEN': csrfToken
        },
        success: function (data, status, XhrObj) {
            // Do some stuff
        },
        error: function (XhrObj, status, error) {
            // Do some other stuff
        }
    });
    

Where I'm getting stuck is I keep getting the error response {"detail":"CSRF Failed: CSRF token missing or incorrect."} I have attempted to follow the instructions listed in Django's documentation for adding the CSRF header into requests, however the getCookie function they declare there always returns null because the page I'm doing this from is not from that domain (remember it's inside the Chrome plugin "domain") and therefore doesn't have access to my cookies (rightfully so).

Further in that documentation they mention that "If you activate CSRF_USE_SESSIONS, you must include the CSRF token in your HTML and read the token from the DOM with JavaScript." However, doesn't including that token in your HTML completely defeat the purpose of the CSRF token? I.e. it allows an attacker an endpoint to obtain a valid CSRF token which they could then use to execute a malicious attack, correct?

I also looked into being able to get the cookie value directly from the AJAX response, however that is also blocked to prevent the exact type of "Attack" I'm attempting to do.

I do see when I inspect the traffic that the cookie named 'csrftoken' is being sent with my request, so I guess I'm also a little confused as to why/how Django expects me to pull that out to an HTTP header instead of just reading it from the cookie that's getting sent already.

So, I guess, two questions:

  1. Doesn't Django including the CSRF token in HTML completely defeat the purpose of said CSRF token?
  2. What is the way to submit data to a remote API without opening up security holes from a Chrome extension?
Kenny Loveall
  • 519
  • 4
  • 16

1 Answers1

3

So I actually ended up solving this myself (although @wOxxOm pointed me in the right direction).

2 things needed to change to make it work:

  1. Instead of using the Django-suggested way of getting the cookie, I had to use the chrome.cookies API as suggested by wOxxOm.
  2. Change the http Header from HTTP_X_CSRFTOKEN to X-CSRFToken.

Thanks for your help and hopefully this helps someone else!

Also, in regards to my first question, it turns out that the CSRF token included in forms in just a hash of the CSRF token in the cookie, and both forms have to be present in django-generated forms for it to pass CSRF verification, as documented in the Django documentation.

Kenny Loveall
  • 519
  • 4
  • 16
  • Thanks for coming back and answering your own question @Kenny , this was really helpful and nice of you :) – Tomiwa Jun 28 '20 at 12:16
  • Allowing `chrome.cookies` API would also allow you to read all cookies from all sites listed in `host_permissions` in manifest.json. That would be bad for security reasons - you can potentially stole the session cookies from those sites. – Flaiming Mar 10 '23 at 14:34