Search code examples
djangodjango-rest-frameworkdjango-authentication

Django REST Framework allow only superusers to access api web view


I'm using Django 2.0 and Django RESET Framework to write REST API for my application.

I have configured following authentication methods

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
}

As of now, It allows all authenticated users to access web api view.

What I want is to allow few users (probably superadmin users) to be able to access API from Session Authentication or from web browser by logging in.

Edit 2: contacts/views.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated,)

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)

Solution

  • So you can leverage permission_classes to do this. DRF's Request object remembers the authentication method that was used in an attribute called _authenticator. You can use this; and use the permission_classes to determine if the pair of (user, authenticator) has permission

    class AdminAuthenticationPermission(permissions.BasePermission):
        ADMIN_ONLY_AUTH_CLASSES = [rest_framework.authentication.BasicAuthentication, rest_framework.authentication.SessionAuthentication]
    
        def has_permission(self, request, view):
            user = request.user
            if user and user.is_authenticated():
                return user.is_superuser or \
                    not any(isinstance(request._authenticator, x) for x in self.ADMIN_ONLY_AUTH_CLASSES) 
            return False
    
    class ContactViewSet(viewsets.ModelViewSet):
        queryset = Contact.objects.all()
        serializer_class = ContactSerializer
        permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)
    

    Untested: but should work