0

I currently have a Django setup that followed the guide below. Pretty much, it's a workaround that allows for HTTPOnly cookies to be used with Django Rest Framework JWT authentication. It worked fine in Django 3.2, but I'm attempting to upgrade to Django 4, and I'm now running into the error below

How to store JWT tokens in HttpOnly cookies with DRF djangorestframework-simplejwt package?

Error:

__init__() missing 1 required positional argument: 'get_response'

I'm still a bit new to Django and DRF, so I have no idea what could be going on.

Edit:

Apologies, forgot to add some details. The error is in the following code, on CSRFCheck():

   from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings

from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions


def enforce_csrf(request):
    # Enforce CSRF validation.
    check = CSRFCheck()
    check.process_request(request)
    # populates request.META['CSRF_COOKIE'], which is used in process_view()
    reason = check.process_view(request, None, (), {})

    if reason:
        # CSRF failed, bail with explicit error message
        raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)


class CustomAuthentication(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

Traceback messages: (Full error: jsfiddle.net/Luizram/t7u03cqy/1 )

/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py, line 55, in inner

        return inner

    else:

        @wraps(get_response)

        def inner(request):

            try:

                response = get_response(request) <- Line 55

 …

            except Exception as exc:

                response = response_for_exception(request, exc)

            return response

        return inner

Local vars /usr/local/lib/python3.8/site-packages/django/core/handlers/base.py, line 197, in _get_response

        if response is None:

            wrapped_callback = self.make_view_atomic(callback)

            # If it is an asynchronous view, run it in a subthread.

            if asyncio.iscoroutinefunction(wrapped_callback):

                wrapped_callback = async_to_sync(wrapped_callback)

            try:

                response = wrapped_callback(request, *callback_args, **callback_kwargs) <- Line 197

 …

            except Exception as e:

                response = self.process_exception_by_middleware(e, request)

                if response is None:

                    raise

        # Complain if the view returned None (a common error).

Local vars /usr/local/lib/python3.8/site-packages/django/views/decorators/csrf.py, line 54, in wrapped_view

def csrf_exempt(view_func):

    """Mark a view function as being exempt from the CSRF view protection."""

    # view_func.csrf_exempt = True would also work, but decorators are nicer

    # if they don't have side effects, so return a new function.

    def wrapped_view(*args, **kwargs):

        return view_func(*args, **kwargs) <- Line 54

 …

    wrapped_view.csrf_exempt = True

    return wraps(view_func)(wrapped_view)

Local vars /usr/local/lib/python3.8/site-packages/django/views/generic/base.py, line 84, in view

            self = cls(**initkwargs)

            self.setup(request, *args, **kwargs)

            if not hasattr(self, "request"):

                raise AttributeError(

                    "%s instance has no 'request' attribute. Did you override "

                    "setup() and forget to call super()?" % cls.__name__

                )

            return self.dispatch(request, *args, **kwargs) <- Line 84

 …

        view.view_class = cls

        view.view_initkwargs = initkwargs

        # __name__ and __qualname__ are intentionally left unchanged as

        # view_class should be used to robustly determine the name of the view

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 509, in dispatch

                                  self.http_method_not_allowed)

            else:

                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:

            response = self.handle_exception(exc) <- Line 509

 …

        self.response = self.finalize_response(request, response, *args, **kwargs)

        return self.response

    def options(self, request, *args, **kwargs):

        """

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 469, in handle_exception

        exception_handler = self.get_exception_handler()

        context = self.get_exception_handler_context()

        response = exception_handler(exc, context)

        if response is None:

            self.raise_uncaught_exception(exc) <- Line 469

 …

        response.exception = True

        return response

    def raise_uncaught_exception(self, exc):

        if settings.DEBUG:

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 480, in raise_uncaught_exception

    def raise_uncaught_exception(self, exc):

        if settings.DEBUG:

            request = self.request

            renderer_format = getattr(request.accepted_renderer, 'format')

            use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')

            request.force_plaintext_errors(use_plaintext_traceback)

        raise exc <- Line 480

 …

    # Note: Views are made CSRF exempt from within `as_view` as to prevent

    # accidental removal of this exemption in cases where `dispatch` needs to

    # be overridden.

    def dispatch(self, request, *args, **kwargs):

        """

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 497, in dispatch

        self.args = args

        self.kwargs = kwargs

        request = self.initialize_request(request, *args, **kwargs)

        self.request = request

        self.headers = self.default_response_headers  # deprecate?

        try:

            self.initial(request, *args, **kwargs) <- Line 497

 …

            # Get the appropriate handler method

            if request.method.lower() in self.http_method_names:

                handler = getattr(self, request.method.lower(),

                                  self.http_method_not_allowed)

            else:

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 414, in initial

        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.

        version, scheme = self.determine_version(request, *args, **kwargs)

        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted

        self.perform_authentication(request) <- Line 414

 …

        self.check_permissions(request)

        self.check_throttles(request)

    def finalize_response(self, request, response, *args, **kwargs):

        """

        Returns the final response object.

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 324, in perform_authentication

        """

        Perform authentication on the incoming request.

        Note that if you override this and simply 'pass', then authentication

        will instead be performed lazily, the first time either

        `request.user` or `request.auth` is accessed.

        """

        request.user <- Line 324

 …

    def check_permissions(self, request):

        """

        Check if the request should be permitted.

        Raises an appropriate exception if the request is not permitted.

        """

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/request.py, line 227, in user

    def user(self):

        """

        Returns the user associated with the current request, as authenticated

        by the authentication classes provided to the request.

        """

        if not hasattr(self, '_user'):

            with wrap_attributeerrors():

                self._authenticate() <- Line 227

 …

        return self._user

    @user.setter

    def user(self, value):

        """

        Sets the user on the current request. This is necessary to maintain

Local vars /usr/local/lib/python3.8/site-packages/rest_framework/request.py, line 380, in _authenticate

    def _authenticate(self):

        """

        Attempt to authenticate the request using each authentication instance

        in turn.

        """

        for authenticator in self.authenticators:

            try:

                user_auth_tuple = authenticator.authenticate(self) <- Line 380

 …

            except exceptions.APIException:

                self._not_authenticated()

                raise

            if user_auth_tuple is not None:

                self._authenticator = authenticator

Local vars /django/users/authenticate.py, line 30, in authenticate

        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) <- Line 30

 …

        return self.get_user(validated_token), validated_token

Local vars /django/users/authenticate.py, line 10, in enforce_csrf

from rest_framework.authentication import CSRFCheck

from rest_framework import exceptions

def enforce_csrf(request):

    # Enforce CSRF validation.

    check = CSRFCheck() <- Line 10

 …

    check.process_request(request)

    # populates request.META['CSRF_COOKIE'], which is used in process_view()

    reason = check.process_view(request, None, (), {})

    if reason:

        # CSRF failed, bail with explicit error message
Luiz
  • 3
  • 2
  • Please include relevant parts of your code. – ewokx Jul 04 '22 at 23:35
  • @ewong Sorry about that, I've added it – Luiz Jul 04 '22 at 23:41
  • Please include the full error traceback message, not just the final line. – John Gordon Jul 04 '22 at 23:45
  • This is a little confusing. Please just include the full traceback error as-is and your code as-is. – ewokx Jul 04 '22 at 23:58
  • @ewong Sorry about that. The error is quite long. I've but the entire thing in a jsfiddle so it's human readable https://jsfiddle.net/Luizram/t7u03cqy/1/ I also added arrows with the line numbers it's mentioning in the post if that helps – Luiz Jul 05 '22 at 00:05

0 Answers0