How to add partitioned attribute to cookies in Django ?

My backend is hosted on render and i was testing the email OTP functionality, but on making a GET request to “/register/” endpoint to get the “csrftoken” i am getting this:

Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.

null live.html:58:17

GET

http://127.0.0.1:8001/favicon.ico

[HTTP/1 404 File not found 0ms]

Cookie warnings 2

Cookie “csrftoken” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute. register

Cookie “csrftoken” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute. register

{"message": "CSRF token set."}

views.py:

@ensure_csrf_cookie
def register(request):
    if request.method == "POST":
        # email = request.POST.get("email")
        try:
            # Parse the JSON body
            data = json.loads(request.body)
            email = data.get("email")
        except json.JSONDecodeError:
            return JsonResponse({"success": False, "message": "Invalid JSON format."})

        try:
            validate_email(email)
        except ValidationError:
            return JsonResponse({"success": False, "message": "Invalid email format."})

        email_otp = generate_otp()
        redis_key = f"otp:{email}"

        cache.set(redis_key, email_otp)

        try:
            message = BaseEmailMessage(
                template_name="emails/otp_template.html",
                context={"email_otp": email_otp},
            )
            message.send([email])
        except (BadHeaderError, SMTPException) as e:
            return JsonResponse(
                {"success": False, "message": f"Failed to send OTP. Error: {str(e)}"}
            )

        return JsonResponse(
            {
                "success": True,
                "message": "OTP sent successfully. Please check your email.",
            }
        )

    return JsonResponse({"message": "CSRF token set."})


def verify_otp(request):
    if request.method == "POST":
        # email = request.POST.get("email")
        # user_otp = request.POST.get("otp")
        try:
            # Parse the JSON body
            data = json.loads(request.body)
            email = data.get("email")
            user_otp = data.get("otp")
        except json.JSONDecodeError:
            return JsonResponse({"success": False, "message": "Invalid JSON format."})

        if not email or not user_otp:
            return JsonResponse(
                {"success": False, "message": "Email and OTP are required."}
            )

        redis_key = f"otp:{email}"
        stored_otp = cache.get(redis_key)

        if stored_otp is None:
            return JsonResponse(
                {"success": False, "message": "OTP expired or not found."}
            )

        if validate_otp(stored_otp, user_otp):
            cache.delete(redis_key)
            return JsonResponse(
                {"success": True, "message": "OTP verified successfully."}
            )
        else:
            return JsonResponse({"success": False, "message": "Invalid OTP."})

    return JsonResponse({"success": False, "message": "Invalid request method."})

live.html (http://127.0.0.1:8001/live.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register and Verify OTP</title>
</head>
<body>

    <h1>Register</h1>

    <!-- Email Form -->
    <form id="registerForm" method="POST" action="https://shop-sphere-app.onrender.com/register/">
        <label for="email">Email: </label>
        <input type="email" id="email" name="email" required>
        <button type="submit">Send OTP</button>
    </form>

    <!-- OTP Verification Form (Initially hidden) -->
    <div id="otpForm" style="display: none;">
        <h2>Enter OTP</h2>
        <form id="verifyOtpForm" method="POST" action="https://shop-sphere-app.onrender.com/verify_otp/">
            <label for="otp">OTP: </label>
            <input type="text" id="otp" name="otp" required>
            <button type="submit">Verify OTP</button>
        </form>
        <div id="otpMessage"></div>
    </div>

    <div id="errorMessage" style="color: red;"></div>

    <script>
        // Fetch CSRF token by making a GET request to Django
        fetch("https://shop-sphere-app.onrender.com/register/", {
            method: "GET",
            credentials: "include",
        })
        .then(response => response.text())
            .then((res) => console.log(res));

         // Function to get CSRF token from cookies
        function getCookie(name) {
            let cookieValue = null;
            if (document.cookie && document.cookie !== "") {
                const cookies = document.cookie.split(";");
                for (let i = 0; i < cookies.length; i++) {
                    const cookie = cookies[i].trim();
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }

        const csrftoken = getCookie("csrftoken");
        console.log(csrftoken);

        // Handle email registration form submission
        document.getElementById("registerForm").addEventListener("submit", function(event) {
            event.preventDefault(); // Prevent form submission
            let email = document.getElementById("email").value;
            fetch("https://shop-sphere-app.onrender.com/register/", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRFToken": csrftoken, // Include CSRF token in the headers
                },
                credentials: "include",
                body: JSON.stringify({ email: email }),
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // Show OTP form on successful OTP sent
                    document.getElementById("otpForm").style.display = "block";
                    document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
                } else {
                    // Show error message if OTP wasn't sent successfully
                    document.getElementById("errorMessage").textContent = data.message;
                }
            })
            .catch(error => {
                console.log(error);
                document.getElementById("errorMessage").textContent = "An error occurred while sending OTP.";
            });
        });

        // Handle OTP verification form submission
        document.getElementById("verifyOtpForm").addEventListener("submit", function(event) {
            event.preventDefault(); // Prevent form submission
            let email = document.getElementById("email").value;
            let otp = document.getElementById("otp").value;

            fetch("https://shop-sphere-app.onrender.com/verify_otp/", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRFToken": csrftoken, // Include CSRF token in the headers
                },
                credentials: "include",
                body: JSON.stringify({ email: email, otp: otp }),
            })
            .then(response => response.json())
            .then(data => {
                const otpMessageDiv = document.getElementById("otpMessage");
                if (data.success) {
                    otpMessageDiv.style.color = "green";
                    otpMessageDiv.textContent = data.message;
                } else {
                    otpMessageDiv.style.color = "red";
                    otpMessageDiv.textContent = data.message;
                }
            })
            .catch(error => {
                document.getElementById("otpMessage").textContent = "An error occurred during OTP verification.";
            });
        });
    </script>

</body>
</html>

prod.py:

CSRF_TRUSTED_ORIGINS = ["http://127.0.0.1:8001"]

CSRF_COOKIE_SAMESITE = "None"
CSRF_COOKIE_SECURE = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
    "http://127.0.0.1:8001",
    "http://localhost:8001",
]

From what I can see, direct support for this is not yet implemented in Django.

Additionally, it’s not even a standard yet - which means it could undergo changes before being ratified. In fact, it looks like work on this has stalled, the last draft expired almost 2 years ago. I also can’t find any email in the IETF working group archives since 2022 about it. (Granted, this is a rather cursory search.)

See draft-cutler-httpbis-partitioned-cookies-01 - Cookies Having Independent Partitioned State specification

IF these are going to become “mandatory”, I can’t see it happening anytime soon.

Is there any way to work around this ?

Work around what?

What is generating that message? (That’s not Django producing that.)

Yeah i know. I meant any work around for the browser error ?

What browser error? I see a couple of warnings in what you posted, but that’s about it.

Cookie warnings 2

Cookie “csrftoken” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute. [register](https://shop-sphere-app.onrender.com/register/)

Cookie “csrftoken” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute.

this warning is now allowing the csrftoke to be set in the cookies.

What browser are you using?

i am using fireox (OS: Arch)

Then I would look for a setting in Firefox to not check this. If Firefox is rejecting the cookies because of this, then it’s a problem with Firefox.

Okay, i will see what i can do. Thnx as always

(post deleted by author)