Skip to content
Advertisement

Django – Have a user logged in authentication check on every REST API call

I have this code of 2 views in Django. You will notice that each REST API call has a verify_login() function call that ensures that the request contains a verified JWT token. I’m wondering if there’s a better way to implement this so that I don’t have to have these lines specifically in every REST endpoint

    verify_response = verify_login(request)
    if verify_response not None:
        return verify_response

I’m trying to follow the D.R.Y. (Do Not Repeat Yourself) principle of coding. It’d be nice if there was a cleaner way to represent this. I thought about maybe creating a module extending APIView that automatically has this and then all my Views extend that, but runs into the issue of having to call super().API_REQUEST() and then having to do the same if-statement check to see if it’s None or not.

class PostView(APIView):
    """
    View for Post object

    * requires token authentication
    """
    # Create post
    @swagger_auto_schema(
        request_body=PostSerializer,
        operation_description="Create a post object"
    )
    def post(self, request):
        verify_response = verify_login(request)
        if verify_response not None:
            return verify_response

        serializer = PostSerializer(data=request.data)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # get all posts
    @swagger_auto_schema(
        operation_description="Get all posts from the DB"
    )
    def get(self, request):
        verify_response = verify_login(request)
        if verify_response not None:
            return verify_response

        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

Advertisement

Answer

You can use authentication classes alongside permission classes. If you want the authentication check to happen for all the APIs of your application, put your classes in settings.REST_FRAMEWORK. If you want it for specific APIView’s, put them in permission_classes & authentication_classes class variables. Check out the doc for more details.

Example,

class JWTAuthenticataion(BaseAuthentication):
    def authenticate(self, request):
        ...    # write your JWT implementation here


# settings.py:
REST_FRAMEWORK = {
    ...
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "path.to.JWTAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.IsAuthenticated",
    )
}

# or
# api.py
class YourAPIView(APIView):
    permission_classes = (IsAuthenticated, )
    authentication_classes = (JWTAuthentication, )

    ...
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement