4

I've used token authentication, and it's working fine i.e. it is authenticating a user and then the user is logged in. But in my views I've set permission classes to IsAuthenticated for one of the views, and it is not allowing to the user even if he is an authenticated user. Below is the screenshot where it says i'm logged in (jadhav@gmail.com) :

enter image description here

and the very next tab to this, it says "authentication details not provided":

enter image description here

Can someone tell what's wrong? ok, I'm providing details: these are my settings:

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

This is how I authenticated:

class UserLoginAPIView(APIView):

permission_classes = [AllowAny]
serializer_class = UserLoginSerializer

def post(self, request, *args, **kwargs):
    data = request.data
    serializer = UserLoginSerializer(data=data)
    if serializer.is_valid(raise_exception=True):
        # new_data = serializer.data
        if serializer.data:
            user = authenticate(username=request.data['username'], password=request.data['password'])
            login(request, user)
            print("IsAuthenticated", user.is_authenticated)
        token, _ = Token.objects.get_or_create(user=user)
        return Response({'token': token.key},
                        status=HTTP_200_OK)

Another View where I put restrictions:

class BoardCreateAPIView(CreateAPIView):

queryset = Boards.objects.all()
serializer_class = BoardCreateSerializer
permission_classes = (IsAuthenticated,)
user10058776
  • 183
  • 1
  • 3
  • 17
  • I don't think the built in api docs allow posts? I could be wrong. check the browser dev tools and make sure you're actually sending a post with the token. That said, you should add more information about how you're adding permission classes and how you're adding the token – Jason Dec 08 '18 at 12:33
  • also, the header required for authentication is `Authorization`, so make sure your token is there – Jason Dec 08 '18 at 12:34
  • you can use Postman for set authentication on header – Ali Dec 08 '18 at 12:48
  • @Jason Edited to provide more info – user10058776 Dec 08 '18 at 13:13
  • @MohammadAli tried to provide more info, may now you can tell where I messed up.. – user10058776 Dec 08 '18 at 13:15
  • @user10058776 have you checked my answer below? do you now get a clear picture of the flow? – Ken4scholars Dec 08 '18 at 15:41
  • @Ken4scholars I checked user password(used django 'authenticate' function), in validate method of my serializer, and now trying to pass that user to my views where token is to be generated. But I'm facing problem how to catch the values using 'serializer.validated_data[' ']' in my views. – user10058776 Dec 08 '18 at 16:01
  • @user10058776 you don't need to use the django authenticate function. First get the user using the login, then call `user.check_password(password)`. If it returns true then add the user to the `validated_data` which you can access in the view using `serializer.validated_data['user']` – Ken4scholars Dec 08 '18 at 16:37

2 Answers2

2

Just as @Reza hinted, you're missing the point of token authentication. You're trying to use the basic authentication flow instead. The flow is like this:

  1. Client requests a token from the server using login and password
  2. Server verifies that your credentials are correct, creates a token and returns it to the client
  3. In subsequent requests, client adds the token to the Auth header like this:

    Authorization: Token <the_client_token>

So what you should do in your login view is verify the user credentials and create a token. you shouldn't try to perform the authentication yourself. You can rename the view to obtain_token so as not to confuse its function.

Check the article @Reza linked for more info.

Ken4scholars
  • 6,076
  • 2
  • 21
  • 38
1

In django rest framework, You should provide token in your request headers. here is the sample with curl command:

curl -X POST -H "Content-Type: application/json" -H "Authorization: Token <MY_TOKEN>" http://my-api-url

Also check that in your settings.py at least you have these lines:

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

For more understanding read this doc from django rest framework

Reza Torkaman Ahmadi
  • 2,958
  • 2
  • 20
  • 43