Home > Blockchain >  In Django REST framework's authentication, how do I set the default access scheme to allow all
In Django REST framework's authentication, how do I set the default access scheme to allow all

Time:10-12

I'm using Django 3.2 and djangorestframework==3.12.2. I recently added this to my settings file because I want to add some secured endpoints to my application ...

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
         'rest_framework.permissions.IsAuthenticated',
         'rest_framework.permissions.IsAdminUser',
         ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    )
}

JWT_AUTH = {
    # how long the original token is valid for
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),

}

However, this seems to have caused all my endpoints to require authentication. For example, I had this view set up in my views.py file

class CoopList(APIView):
    """
    List all coops, or create a new coop.
    """
    def get(self, request, format=None):
        contains = request.GET.get("contains", "")
        if contains:
            coops = Coop.objects.find(
                partial_name=contains,
                enabled=True
            )
        else:
            partial_name = request.GET.get("name", "")
            enabled_req_param = request.GET.get("enabled", None)
            enabled = enabled_req_param.lower() == "true" if enabled_req_param else None
            city = request.GET.get("city", None)
            zip = request.GET.get("zip", None)
            street = request.GET.get("street", None)
            state = request.GET.get("state", None)
            coop_types = request.GET.get("coop_type", None)
            types_arr = coop_types.split(",") if coop_types else None

            coops = Coop.objects.find(
                partial_name=partial_name,
                enabled=enabled,
                street=street,
                city=city,
                zip=zip,
                state_abbrev=state,
                types_arr=types_arr
            )
        serializer = CoopSearchSerializer(coops, many=True)
        return Response(serializer.data)

accessible in my urls.py file using

path('coops/', views.CoopList.as_view()),

But now when I try and call that I get the below response

{"detail":"Authentication credentials were not provided."}

I only want certain views/endpoints secured. How do I make the default that all views are accessible and only specify some views/endpoints to be validated using a provided JWT?

CodePudding user response:

'DEFAULT_PERMISSION_CLASSES' is conventiently applied to all views, unless manually overridden. In your case both listed permissions require the user to be authenticated. FYI, the list is evaluated in an OR fashion.

If you want to allow everyone by default and only tighten down specific views, you want to set

'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny']

which does not require the user to be authenticated. Then set more strict permissions explicitly on the view (e.g. permissions_classes = [IsAuthenticated]) The DEFAULT_AUTHENTICATION_CLASS can stay as is.

NOTE: It is generally advisable to do it the other way round. It's very easy to accidentally expose an unsecured endpoint like this and potentially create a security breach in your API. The default should be secure and then exceptions should be be manually lifted.

CodePudding user response:

Set the below configuration in settings.py

'DEFAULT_PERMISSION_CLASSES': [
   'rest_framework.permissions.IsAuthenticated',
]

For class based views you can set permission class to empty list.

class CoopList(APIView):
    permission_classes = []
  
    def get(self, request, format=None):
        pass
    

For Function based views add the decorator @permission_classes

from rest_framework.decorators import permission_classes

@permission_classes([])
def CoopList(request, format=None):
    pass 
  • Related