CSRF Token missing

I can’t stress this enough, Django csrf need a rework, it sucks so much, the problem im going to relate below is in a production enviroment:

What is happening exactly is that im able to generate the csrftoken it is being set in the request headers, but when I try to actually login I get a CSRF token missing; error.

IN DEVELOMENT THIS IMPLEMENTATION WORKS

Backend:

settings.py

MIDDLEWARE = [
    "whitenoise.middleware.WhiteNoiseMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

CORS_ALLOWED_ORIGINS = ["app.link"]

CSRF_TRUSTED_ORIGINS = ["app.link"]

CSRF_COOKIE_NAME = "csrftoken"

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.SessionAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",),
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
    "PAGE_SIZE": 10,
}

account/views.py

@method_decorator(csrf_protect, name="dispatch")
class Login(APIView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        """Login"""

        email = request.data["email"]
        password = request.data["password"]

        try:
            user = authenticate(request, email=email, password=password)
            if user is not None:
                login(request, user)

                if user.type == "A":
                    serializer = AdminSerializer(user.admin)
                elif user.type == "P":
                    serializer = PersonSerializer(user.person)
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(status=status.HTTP_401_UNAUTHORIZED)
        except:
            return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

Frontend:

api/api.config.ts

import axios from "axios";

const api = axios.create({
  baseURL: "app.link",
});

api.defaults.xsrfCookieName = "csrftoken";
api.defaults.xsrfHeaderName = "X-CSRFToken";
api.defaults.withCredentials = true;

export default api;

pages/admin.tsx

  const handleLoginAdmin = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    try {
      return api.get("auth/csrf").then(async (response) => {
        if (response.status !== 200) throw new Error(response.statusText);
        await api.post("auth/login", data).then((response) => {
          if (response.status !== 200) throw new Error(response.statusText);
          const { id, group, role } = response.data;
          setCurrentAdmin({ id, group, role });
          router("/clinic");
        });
      });
    } catch (error) {
      setError("Erro ao fazer login");
      return Promise.reject();
    }
  };

Requests:

(Album — Postimages)

The entries on this list must have the scheme as part of the specification - see the docs for CSRF_TRUSTED_ORIGINS. (Also see the docs for CORS_ALLOWED_ORIGINS.)

We’re going to need to see your actual entries for those fields if you need more specific guidance - along with the details of where the front end is being loaded from along with the full urls being requests.

@KenWhitesell yes sir, on the actual code they have that structure, I’ve just omitted them out.

But it is in the correct format http://*.example.com

Let’s pretend the link entry is http://localhost:5137, the frontend calls localhost:8000/api/auth/csrf to fetch the token, then it calls localhost:8000/api/auth/login to login. That’s it as I’ve said this implementation works in development but not in production

If by “development vs production” what you really mean is DEBUG = True vs DEBUG = False, that is to be expected. Having DEBUG = True alters a number of internal operations. Pointing out that something works in development and not in production provides no diagnostic value.

The error mesage you’re posting:

What is api/auth/csrf returning to the client? Is it returning the csrf_token to the client? Is the client then adding that to the data being posted? (Are you seeing that being returned in the post data? (The images you referenced show the headers but not the content.)

Side note: For future reference, please include the complete error message and traceback for any errors for which you’re requesting assistance.

You may wish to read How to use Django’s CSRF protection | Django documentation | Django for more details about how this works.

Sure everything should be here

What I don’t understand is the fact that you are saying that the csrf token should be added to the request body, I’ve never done it that way, its just always been able to get the csrft token from the headers, but no currently im not passing the csrf token directly in the body of the post request just the headers, (which as I’ve said before should work based on previous experiences).

Now I’ve tried it with including the token in the body of the request and it still doesn’t work, same error btw.

Please show the details. Show what you’re posting as the content and the headers, and the complete error - both what’s being returned in the response and what is showing up in the console.

Yes, that’s a valid way to do it.

However, in the images you’ve posted, I do not see an X-CSRFToken header.
(I see the cookie, but not the token, which is what the error message is complaining about.)

Hey sorry for not replying I found out what it was, some weird behavior with axios, thanks for trying to help tho