Home > database >  How to block user authorization for Django Rest Framework in custom Middleware?
How to block user authorization for Django Rest Framework in custom Middleware?

Time:10-31

Hi I am creating a custom middleware in Django for the DRF.

So that when an user try to access any of the api the middleware will perform some operation and determine if the user is authorized to access the endpoint or not.

My code is like below:

class PermissionMiddleware(MiddlewareMixin):
    def process_view(self, request, view_func, view_args, view_kwargs):
        if request.path.startswith('/admin/'):
            return None


        if request.path.startswith('/api/'):
            is_allowed = True
            if not is_allowed:
                return # < -- What needs to return to block the access
            return None

My problem is what should I return from the method for disallowing access to api? I can return None, if I want to give access. But I want to disallow access and return some message from the api view so that user knows that he is not allwed.

So in summery:

  1. What should I return from the middleware to block access?
  2. How can I return message to user from the view that he is not authorized?

Thanks

CodePudding user response:

Let's say you want to restrict access to your endpoint.

  1. To achieve this you have two view's methods for that:
    check_permissions - gets to decide whether the request and user are allowed to proceed. check_object_permissions - gets to decide whether a user is allowed to interact with an object.
  2. To define your custom validation logic you can subclass BasePermission class from rest_framework:
    class YourCustomPermission(permissions.BasePermission):
    
        # Will be retrieved from the view's methods mentioned above
        custom_message = 'Your message.'
    
        def has_permission(self, request, view):
            if is_your_custom_request_logic_satisfied(request):
                return True
            return False
    
        def has_object_permission(self, request, view, obj):
            if is_your_custom_object_logic_satisfied(request, obj):
                return True
            return False 
    
  3. And finally your view:
    class APIView(View):
        ...
        permission_classes = [IsAuthenticated, YourCustomPermission]
    
        def check_permissions(self, request):
            for permission in self.get_permissions():
                if not permission.has_permission(request, self):
                    self.permission_denied(
                        request,
                        message=getattr(permission, 'custom_message', None),
                        code=getattr(permission, 'code', None)
                    )
    
        def check_object_permissions(self, request, obj):
            for permission in self.get_permissions():
                if not permission.has_object_permission(request, self, obj):
                    self.permission_denied(
                        request,
                        message=getattr(permission, 'custom_message', None),
                        code=getattr(permission, 'code', None)
                    )
    

Here is a nice tutorial for you to read.

CodePudding user response:

This is approch I took to get the result I was expecting. This way I do not have to modify api view. Hope it will help others in the future.

from django.http import JsonResponse


class PermissionMiddleware(MiddlewareMixin):
    def process_view(self, request, view_func, view_args, view_kwargs):
        if request.path.startswith('/admin/'):
            return None


        if request.path.startswith('/api/'):
            is_allowed = True
            if not is_allowed:
                return JsonResponse(
                    {"detail": "Subscription Expired or Not Subscribed"}, 
                     status=403
                )
            return None

CodePudding user response:

Youre nearly there, you should raise a

PermissionDenied

Error and this would be handled appropriately.

This error would then be handled like so:

https://docs.djangoproject.com/en/4.1/topics/http/middleware/#process-exception

  • Related