[Django]-Token authentication in django (rest_framework) not working

4👍

This login_required is not rest_frameworks way to authenticate. You need to use permission class for authenticating through your api if that’s what you are trying to do.
How I implemented it was, I created a view for login

class LoginView(APIView):
    """Class based view loggin in user and returning Auth Token."""

    authentication_classes = [TokenAuthentication]
    permission_classes = [AllowAny]

    def post(self, request):
        """Check if user exists, return token if it does."""
        data = JSONParser().parse(request)
        serializer_obj = LoginObjectSerializer(data=data)
        if serializer_obj.is_valid():
            user = authenticate(username=serializer_obj.data['username'], password=serializer_obj.data['password'])
            if not user:
                return Response({'error': 'Invalid Credentials'}, status=404)
            token, _ = Token.objects.get_or_create(user=user)
            return Response({'token': token.key}, status=200)

        return JsonResponse(serializer_obj.errors, status=400)

And how I authenticated my APIs was by using rest-framework‘s provided permission classes instead of @login_required.
My settings.py has

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated', )
}

and the permission class I used to secure my views was like this

from rest_framework.permissions import AllowAny, IsAuthenticated

authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]

But I used like this in class based views. For method based, you can do this as mentioned here

@permission_classes([IsAuthenticated])

The crux of this is, you are trying to use token based authentication but you are not actually using it. Create your own login api,and use it like mentiond in this answer or the answer of @sebastienbarbier.

👤saadi

0👍

Your problem come from the use of the decorator @login_required which is suppose to protect a django view.

Django views and django_rest_framework do not use the same authentication system and so need to be implemented differently.

Manual authentication

You can remove @login_required and implement view.py as followed :

from rest_framework.authentication import TokenAuthentication
...
@csrf_exempt
def ui_list(request):
    print(request.headers)
    """
    List all code user_informations, or create a new user_information.
    """
    if request.method == "GET":

        user_auth_tuple = TokenAuthentication().authenticate(request)
        if user_auth_tuple is None:
            return HttpResponse(status=401)
        else:
            (user, token) = user_auth_tuple # here come your user object

            users = UserInformation.objects.all()
            serializer = UserInformationSerializer(users, many=True)
            return JsonResponse(serializer.data, safe=False)
    
    if request.method == "POST":
         ...
...

But doing this process manually is really time consumming, should not be done this way as DRSF provide lots of options to make this automatic.

Class based view

What should actually be done is match a django rest framework APIView class to your model and generate a proper entry point using the permission system.

REST framework provides an APIView class, which subclasses Django’s View class.

APIView classes are different from regular View classes in the following ways:

  • Requests passed to the handler methods will be REST framework’s Request instances, not Django’s HttpRequest instances.
  • Handler methods may return REST framework’s Response, instead of Django’s HttpResponse. The view will manage content negotiation and setting the correct renderer on the response.
  • Any APIException exceptions will be caught and mediated into appropriate responses.
  • Incoming requests will be authenticated and appropriate permission and/or throttle checks will be run before dispatching the request to the handler method.

0👍

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated', ) }

adding rest_framework.authentication.TokenAuthentication worked

👤aoulaa

Leave a comment