CSRF token is null

(Sorry for my English since I am not a English speaker)

Hi all,

I am making an Django Project, and running on 127.0.0.1:8000 for frount end and 127.0.0.1:8001 for the backend
The Frount End have a function for index where

BACK_URL = 'http://127.0.0.1:8001' 
def index(request): 
    return render(request, "peskincomp/index.html", {
        'url': BACK_URL 
    }) 

While the index.html is

{%extends "peskincomp/template.html"%}

{%block body%}

<div class="box">
    <h1>转换 </h1>
    <hr>
    <form method="POST" action="{{url}}/v3/" enctype="multipart/form-data">
        {% csrf_token %}
        <p style="font-size: 20px">请放入皮肤文件开始打包。在打包的过程中您可以添加更多的皮肤文件 </p>
        <br>
        <p style="font-size: 20px">请放入皮肤文件 </p><input type="file" style="font-size: 20px" name="Upload" multiple /> <br>
        <p style="font-size: 20px">请输入皮肤包名称 </p><input type="text" name="name" style="font-size: 20px" text="Default Skin Pack"> <br>
        <input type="submit" value="Convert">
    </form>
</div>
{%endblock%}  

However, when I call the 127.0.0.1:8001/v3

def index(request): 
    num = regenerate() 
    if (request.method == "POST"): 
        name = request.POST["name"] 
        file_list = request.FILES.getlist("Upload") 
        skin_list = fop.start(file_list) 
        try: 
            slm = models.SkinList.objects.get(id=num) 
        except: 
            slm = models.SkinList.objects.create(id=num) 
        slm.skin.set(skin_list) 
        slm.name = name 
        slm.save() 
        return JsonResponse({
            "rid": num 
        }) 

It shows CSRF verification failed. Request aborted.

Help
Reason given for failure:
Origin checking failed - null does not match any trusted origins.

In the HTML, I can see my CSRF token in my F12, but it siad the csrf token is null. Can I ask for the reason of this?

It can be some reason please check one by one:

  1. Ensure that 'django.middleware.csrf.CsrfViewMiddleware' is listed in the MIDDLEWARE setting of your Django project’s settings.py file.

  2. HTTPS vs HTTP: If your front-end and back-end are served over different protocols (e.g., HTTP for front-end and HTTPS for back-end, or vice versa), CSRF protection might fail due to protocol mismatch. Ensure both front-end and back-end are served over the same protocol.

Sorry, but I have checked those. I have used this middleware for both and all in settings.py it is listed.

The problem I think possibly is not this, because if the problem is this, it will proably say “Origin checking failed - http://127.0.0.1:8000 does not match any trusted origins.”, but instead of http://127.0.0.1:8000, it said null does not match any of trusted origins

This implies to me that your app is not setting the origin header.

Check the data that is being submitted to verify the headers being supplied.

No, that’s not what the error message is telling you:

It’s looking for the origin header. See Origin - HTTP | MDN

I see, however I am a little bit confused about where can I set this in my web app? Should I set it in my app or the project or the html page
(Sorry for this because I am new to the web development)

This isn’t really a Django issue. The solution to this is going to be associated with your front-end.

How are you building your front end? Are you using plain JavaScript? Or are you using a framework such as HTMX, Vue, React, jQuery, etc?

How are you loading that front-end code?

Front-end code is also in another Django project lol actually
I have asked ChatGPT, and I don’t know whether this code can work or not?

class CustomOriginMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response 

    def __call__(self, request):
        # Check if the request has the 'Origin' header
        if 'HTTP_ORIGIN' in request.META:
            request.META['HTTP_ORIGIN'] = 'http://127.0.0.1:8000'

        response = self.get_response(request)
        return response 

I don’t know whether it is going to have any side effect after adding this middleware or will it even work

That is really a BAD idea.

It’s worse than that. That’s a phenominally, incredibly, unbelievably, remarkably DANGEROUSLY BAD idea. The first time I would ever get a suggestion like that would be the last time I would ever think of using it to answer a question.

That is intentionally eliminating a key security feature that Django considers important enough to make part of core.

I see. Since I am Django as frount end (without other framework), and I really have searched through the internet last night (Sorry for replying that late becuase I go to bed), I could hardly find a way to modify the header. Could you please sugest a way of modifying this? I understand it is not a problem with Django, I just can’t find a way of solving this, thaknks

You need to post the code for the front end.

Template.html

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
    <title>Title</title>
    <meta name="keywords" content="Tool Box">
    <link href="https://cdn.pmine.org/bootstrap-5.3.2/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.pmine.org/bootstrap-5.3.2/js/bootstrap.bundle.min.js"> </script>
    <link href="https://cdn.pmine.org/fdsprivate/pmine-bs.css" rel="stylesheet">
</head>

<body>
    {% include 'op/zh/navbar.html' %}
    {% block body %}
    {% endblock %}
    {% include 'op/zh/footdiv.html' %}
    <script type="text/javascript" src="https://cdn.pmine.org/jQuery/jquery.js"></script>
</body>

</html>

Index.html

{%extends "peskincomp/template.html"%}

{%block body%}

<div class="box">
    <h1>转换 </h1>
    <hr>
    <form method="POST" action="{{url}}/v3/" enctype="multipart/form-data">
        {% csrf_token %}
        <p style="font-size: 20px">请放入皮肤文件开始打包。在打包的过程中您可以添加更多的皮肤文件 </p>
        <br>
        <p style="font-size: 20px">请放入皮肤文件 </p><input type="file" style="font-size: 20px" name="Upload" multiple /> <br>
        <p style="font-size: 20px">请输入皮肤包名称 </p><input type="text" name="name" style="font-size: 20px" text="Default Skin Pack"> <br>
        <input type="submit" value="Convert">
    </form>
</div>
{%endblock%}  

Thanks

Ok, so the browser loads a page from Django project “A”. That page contains a form that submits that form to Django project “B”.

So no, it’s not accurate to say that Django project “A” is the front-end. The browser is still the front end. In this case, the front end is an html page that was retrieved from Django project “A”.

Now, having said all this, everything I’m reading indicates to me that the browser should be sending the Origin header. So I think the next thing I’d check are the headers being submitted by the form. Use the network tab of your browser’s developer tools to see what it’s actually sending.

This the header when I communicate with the backend and display the 403 page



Instead of loading the site using the ip address 127.0.0.1, try referencing it with the name localhost and see if that allows the Origin header to be populated.

Also, what software are you using to run your Django projects? (Are these both in a development environment using runserver, or a production environment using something like uWSGI or gunicorn?)

When I change my backurl into localhost:8001, it still shows 403, origin = null
While I am using the environment of runserver, not using uWSGI.
I am now tring to run both of my projects on a VPS with my domain, and I will update whether I succeeded by doing this. Thank for your time and paitence

I can’t recreate what you’re seeing here. I’ve tried this in my test environments with all of Edge, Chrome, and Firefox, and I’m seeing the Origin header being set in all cases.

What middleware are you running? Are you running anything other than the standard middleware?

Back end middleware

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware', # Cors 
    'django.middleware.csrf.CsrfViewMiddleware', # Use in non-testing condition 
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Frount end Middleware

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

I am using Edge, while when I use uWGSI, the origin is still null

I know it could be a lot of work, if it is possible could you see whether there is anything wrong wuthin my frountend code? The application is peskincomp

The frountend code archive

Thanks a lot, I really apperitiate your time

This is not something within the code itself. Unless you specifically have code to add or remove a header, your application doesn’t affect this at all. This is outside the scope of your application. It’s either going to be a middleware, wsgi container, or web server issue.

Are you running uWSGI behind a web server such as nginx? Or are you connecting to the uWSGI instance directly?

What does your uwsgi configuration file / command file look like?

In my testing condition, I just use

python manage.py runserver 8000 

And in the uWGSI condition,

[uwsgi]
chdir=/www/wwwroot/v3_pmine

wsgi-file=/www/wwwroot/v3_pmine/pmine/wsgi.py

processes=4

threads=2

pidfile=/www/wwwroot/v3_pmine/uwsgi.pid

http=0.0.0.0:10003
uid=www
gid=www

master=true

daemonize = /www/wwwlogs/python/v3_pmine/uwsgi.log

While in both condition, I failed to get a not null value for the origin
And the header I am listed above, I don’t know whether there are some abnormal things or not affect it, I think I just use the system generated ones

Actually, now that I think about this some more, I think you’ll still encounter other problems.

Even if you do end up resolving this, I think you’re still going to encounter other CSRF and CORS-related issues.

I don’t think this idea is going to work as is.

I’m starting to come to the conclusion that if you’re running both projects on the same system, you may end up needing to run them both behind an nginx instance that allows the browser to be issuing both requests to the same server. You can then configure nginx to separate the traffic between the two projects. (And, it would let you separate this traffic based on name or url, and not just port.)