0
votes

I have a middleware class that looks something like this:

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

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):
        dog_id = view_kwargs.get("dog_id")
        if dog_id is not None:
            dog = Dog.objects.get(id=dog_id)
            request.dog = dog

I have a view that looks something like this:

class DogDetail(APIView):
    def get(self, request, dog_id, *args, **kwargs):
         return "some nice doggy info"

My permissions default to IsAuthenticated:

    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.IsAuthenticated",
    ),

When I call the DogDetail view from a logged-out state, with a dog that doesn't exist, I get a 500 error, and a DoesNotExist exception. I infer from this that the middleware runs before the permissions.

My questions: Is this expected behavior? If not, what am I doing wrong?

If so, it is very un-ideal, because it would be very easy to leak data through middleware. In my example, it would be very easy for a un-authenticated user to determine which dog_id's existed. What is a good way to mitigate this? I guess I could check for authentication in the middleware, and pass unauthenticated requests through without getting the dog_id? That feels like I'm headed for a deep bug in the future where middleware runs properly, but the dog doesn't get attached to the request.

Thank you in advance!

Yes, middleware run before DRF authentication. Since DRF works mostly on the view layer, auth happens in the view (This is what allows you to control authentication on a view level). - Abdul Aziz Barkat