Search code examples
javascriptdjangodjango-rest-frameworkhttp-headersfetch

I cant get my token in permissions even though i send it. Django rest framework


I have created simple permission class to protect my view.

class StaffOnly(permissions.BasePermission):

    def has_permission(self, request, view):
        token = request.META.get('HTTP_TOKEN', False) # Always returns False 
        user = CustomUser.objects.filter(token=token) # Which means no user found
        if user.exists(): # This line won`t execute
            user = user.get(token=token)
            return user.role > 0 
        else:
            raise PermissionDenied('No token')

View itself:

@api_view(["GET"])
@permission_classes([StaffOnly])
def book_list(request):
    book_list = InfoBook.objects.all()
    serializer_list = InfoBookSerializer(book_list, many=True)
    return Response(data=serializer_list.data, status=status.HTTP_200_OK)

Then I was trying to send request from the client side.

// This is the part of React`s Component`s code. I`m sure that I`m not sending blank token and url is correct

        fetch(HTTP + DOMAIN + API + VERSION + GETBOOKS, {
            headers: {
                "Token" : props.token 
            }
        })
          .then(res=>res.json())
          .then(data => setBooks(data))

Unfortunatelly my permission class always denies access because of no token provided. As you can see, Im sending propriate header and I still can`t get access to it for some reason.

Because Im sort of newbie I don``tt know the reason why it is happening.

I``` ve figured out that I can` ``t get access to my token-header in permission class but I can access it inside of view.

# Client`s side request is the same
@api_view(["GET"])
# @permission_classes([StaffOnly]) # disable security from view 
def book_list(request):
    token = request.META.get('HTTP_TOKEN', False) # access token manually 
    print(token) # terminal output is Xg3Fk9DZkpInRvaOipS6UZg9D0x90xV...
    book_list = InfoBook.objects.all()
    serializer_list = InfoBookSerializer(book_list, many=True)
    return Response(data=serializer_list.data, status=status.HTTP_200_OK)

I just wanted to create security permission class that will check certain header named "Token" and give or deny the permission. I`ve faced the problem where this class simply cant get access to this header which in view itself easily accessable.


Solution

  • After being messing with this problems for hours I finally figured out the solution!

    The problem is that there is not just GET request being sent to my "book_list" view but also OPTIONS one. OPTION request is sort of setup thing which always goes before actual request. And it contains NO INFO ABOUT HEADERS DATA, ONLY HEADERS NAMES.

    With that being said the actual solution will look like this:

    class StaffOnly(permissions.BasePermission):
    
    def has_permission(self, request, view):
        if request.method == "OPTIONS": 
            return True #always return true if this is the option request
        #in other case start checking permissions
        token = request.META.get('HTTP_TOKEN', False) 
        user = CustomUser.objects.filter(token=token)
        if user.exists():
            user = user.get(token=token)
            return user.role > 0
        else:
            return False