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?
curl -H "Authorization: JWT <your_token>" http://localhost:8000/api/v1/members/5/
? – agconti