Search code examples
djangodjango-rest-frameworkdjango-csrfcsrf-token

What is the difference between CsrfViewMiddleware and enforce_csrf?


I am trying to apply CSRF token in Django.

I am applying csrf token using middleware and custom authentication.

But I think I'm doing the same process twice.

Because the value of csrf_token from cookie and response is different.

Is it okay to apply+check csrf token by middleware only?

  1. MiddleWare

    settings.py

    CSRF_COOKIE_SECURE = True  # CSRF cookie enabled only Https server
    CSRF_COOKIE_HTTPONLY = True  # CSRF stored in http only cookie
    CSRF_TESTED_ORIGINS = [
    "http://localhost:8000"
    ]
    CSRF_COOKIE_SAMESITE = "Lax"  # Samesite "Lax" - Protection against csrf attacks
    
    MIDDLEWARE = [
    ...
    'django.middleware.csrf.CsrfViewMiddleware'
    ]
    
  2. enforce csrf during authentication

    authenticate.py (I have set CustomAuthentication as DEFAULT_AUTHENTICATION_CLASSES)

    from rest_framework_simplejwt import authentication as jwt_authentication
    from django.conf import settings
    from rest_framework import authentication, exceptions as rest_exceptions
    
    
    def enforce_csrf(request):
        check = authentication.CSRFCheck(request)
        reason = check.process_view(request, None, (), {})
        print(check, reason)
        print(request.META)
        if reason:
            raise rest_exceptions.PermissionDenied('CSRF Failed: %s' % reason)
    
    
    class CustomAuthentication(jwt_authentication.JWTAuthentication):
        def authenticate(self, request):
            header = self.get_header(request)
    
            if header is None:
                raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
            else:
                raw_token = self.get_raw_token(header)
    
            if raw_token is None:
                return None
    
            validated_token = self.get_validated_token(raw_token)
            enforce_csrf(request)
            return self.get_user(validated_token), validated_token
    

    loginView

    response["X-CSRFToken"] = request.COOKIES.get("csrftoken")
    
    

You can check the django csrf documentation here. django documentation


Solution

  • It's not necessary to enforce CSRF protection twice in your code. Django CsrfViewMiddleware is responsible for checking the validity of the CSRF token for incoming requests and for adding the CSRF token to outgoing responses.

    In your custom authentication class, you are using the enforce_csrf function to check the validity of the CSRF token. The same check is already being performed by the CsrfViewMiddleware.

    You can remove the enforce_csrf function from your custom authentication class and rely on the CsrfViewMiddleware to enforce CSRF protection.

    Also, in your loginView code, you are setting the X-CSRFToken header to the value of the csrftoken cookie. This header is not necessary because the CsrfViewMiddleware sets the X-CSRFToken header in the response automatically.