3
votes

When I attempt to do a unit a test I get the error:

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

However, I am using django-rest-framework-jwt, which wants the web token placed at the header as "Authorization: JWT ". I did a wireshark on a working, accepted packet from my website and it had the Authorization: JWT header. As does my current request which is rejected. I can't figure out why it's failing.

Adding force_authenticate allows it to run, but I'd like to test my permissions.

Here is the reference from the Documentation:

Now in order to access protected api urls you must include the Authorization: JWT header.

django-rest-framework-jwt documentation

Here is the request from PyCharm:

{'REQUEST_METHOD': 'PATCH', 
'CONTENT_TYPE': 'application/json; charset=None', 
'CONTENT_LENGTH': 74, 
'PATH_INFO': '/api/v1/members/5', 
'QUERY_STRING': '', 
'Authorization': 'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJlbWFpbCI6ImVtYWlsQGdtYWlsLmNvbSIsInVzZXJfaWQiOjUsImV4cCI6MTQzNzUzOTE4MH0.cGcXw9srOYgbeICdbMw8Ey_ya9eBRD-ptRsGwd2jzlk', 
'wsgi.input': <django.test.client.FakePayload object at 0x106689748>
}

Here is the code:

class ModifyTest(APITestCase):
    """ Test modifying users, to include member_profile
    """
    username = 'user'
    password = 'passwd'
    token = 0
    user_id = 0

    def setUp(self):
        data = {'username': self.username,
                'password': self.password,
                'email': '[email protected]'}
        url = reverse('members:auth-user-create')
        response = self.client.post(url, data, format='json')
        self.user_id = response.data['id']

        data = {'username': self.username,
                'password': self.password}
        url = reverse('token_auth')
        response = self.client.post(url, data, format='json')
        self.token = response.data['token']

    def test_auth_user_info(self):
        data = {'id': str(self.user_id),
                'password': self.password,
                'email': '[email protected]',
                'username': self.username,
                }
        url = reverse('members:auth-user-detail', kwargs={'pk': self.user_id})
        response = self.client.patch(url, data, Authorization='JWT ' + self.token, format='son')
        self.assertEqual(response.status_code, 200)

Update: When stepping through the authentication I realized that my view is not using the correct authentication classes. Below is my settings though...

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        #'rest_framework.authentication.BasicAuthentication',
        #'rest_framework.authentication.SessionAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}

And my view:

class AuthUserDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsOwnerOrAdmin,)
    queryset = get_user_model().objects.all()
    serializer_class = AuthUserModelSerializer

However, my permission classes in my debugger when the view is called are:

<class 'rest_framework.authentication.SessionAuthentication'>, 
<class 'rest_framework.authentication.BasicAuthentication'>

So adding this line to my view fixes it:

authentication_classes = (JSONWebTokenAuthentication,)

But that shouldn't be needed with the default classes selected... any ideas why it isn't using the defaults?

1
What happens when you execute curl -H "Authorization: JWT <your_token>" http://localhost:8000/api/v1/members/5/?agconti
Yah... so below is the reason I wasted way too much time on this problem... hopefully no one else makes that mistake. It took me so long to notice because it was only a factor on modify and I was wiresharking a view that allowed any authentication... not smart, should have done the curl and saved myself hours. ThanksDiesel
Yes i'm facing same error i added autentication_classes =[JSONWebTokenAuthentication]... Thank you !Mbambadev

1 Answers

0
votes

I figured it out... I didn't recognize I had two sections of REST_FRAMEWORK so obviously the second was overwriting the first erasing my defaults... new settings file:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}