The query to my endpoint works fine (as long as I pass it a valid token), it returns the json representation of my response data.
The code in the service api that calls my endpoint, passing an auth token in the header:
headers = {'content-type': 'application/json',
'Authorization': 'Token {}'.format(myToken)}
url = 'http://localhost:8000/my_endpoint/'
r = session.get(url=url, params=params, headers=headers)
In views.py, I have a method decorator that wraps the dispatch method on the view (viewsets.ReadOnlyModelViewSet):
def login_required(f):
def check_login_and_call(request, *args, **kwargs):
authentication = request.META.get('HTTP_AUTHORIZATION', b'')
if isinstance(authentication, str):
authentication = authentication.encode(HTTP_HEADER_ENCODING)
key = authentication.split()
if not key or len(key) != 2:
raise PermissionDenied('Authentication failed.')
user, token = authenticate_credentials(key[1])
return f(request, *args, **kwargs)
return check_login_and_call
I'm trying to write a test to authenticate the request using a token:
from rest_framework.authtoken.models import Token
from rest_framework.test import APIRequestFactory
from rest_framework.test import APITestCase
from rest_framework.test import force_authenticate
class EndpointViewTest(APITestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.user = User.objects.create_user(
username='user@foo.com', email='user@foo.com', password='top_secret')
self.token = Token.objects.create(user=self.user)
self.token.save()
def test_token_auth(self):
request = self.factory.get('/my_endpoint')
force_authenticate(request, token=self.token.key)
view = views.EndpointViewSet.as_view({'get': 'list'})
response = view(request)
self.assertEqual(response.status_code, 200)
json_response = json.loads(response.render().content)['results']
For some reason, I cannot get the request to properly pass the token for this test. Using force_authenticate doesn't seem to change the header that I'm using for validating the token. The current output is raising "PermissionDenied: Authentication failed." because the token isn't being set on the request.
Is there a proper way to set this in the request header in my test or to refactor the way I'm using it in the first place?
I found a way to get the test to pass, but please post if you have a better idea of how to handle any of this.
After changing the above two lines of the test, it seems to authenticate based on the token properly.
Sorry for digging this old thread up, but if someone is using
APIClient()
to do their tests you can do the following:Really good resource that I've used to come up with this is django-rest-framework-jwt tests
I wanted to test the authentication function itself, so forcing authentication wans't an option.
One way to properly pass the token is to use APIClient, which you already have imported.
That sets your given token into the request header and lets the back end decide if it's valid or not.