4
votes

I'm writing some tests to check the connection to my API.

I've put in place identification via tokens and I am successful with retrieving a token for a specific test user with :

token = Token.objects.get(user__username='testuser')

What I'm struggling with is to use that token to create a successful API request as this one :

client = APIClient(HTTP_AUTHORIZATION='Token ' + token.key)
response = client.get('/patientFull/1/',headers={'Authorization': 'Token ' + token.key})

I have been looking at many ways to make this work and these are some ways I tried to do it :

response = requests.get('http://127.0.0.1:8000/patientFull/1/',headers={'Authorization': 'Token ' + token.key} )


client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
response = client.get('/patientFull/1/')

The test is a simple assert to check response has a 200 OK HTTP answer from the server.

All of these ways above returns a 403 HTTP response.

here's the full code of my test (I'm using fixtures to populate my test database with testing data):

import json
import requests
from rest_framework.authtoken.models import Token
from rest_framework.test import APIRequestFactory, APITestCase, APIClient


class CustomerAPITestBack(APITestCase):
    fixtures = ['new-fixtures.json']

    def testDE(self):
        token = Token.objects.get(user__username='jpmichel')
        client = APIClient(HTTP_AUTHORIZATION='Token ' + token.key)
        response = client.get('/patientFull/1/',headers={'Authorization': 'Token ' + token.key})
        self.assertEqual(200, response.status_code)

I have configured my settings.py file as so for the tokens :

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'PHCAdmin.authentication.tokenAuthentication.ExpiringTokenAuthentication',
    ),
    'EXCEPTION_HANDLER': 'PHCAdmin.functions.pxlth_exception_handler',
}

REST_FRAMEWORK_EXPIRY_TIME = 12 # in hours
REST_FRAMEWORK_PASSWORD_RENEWALS = 90 # in days

If I disable the token authentication, this test passes (the GET returns a 200 OK)

How should I do my GET request so that it uses the token to identify as a valid user and returns a 200 OK HTTP response?

2
If you just need to authenticate the user to test other features then you should look at force_authenticate method.5parkp1ug
you can try login first in test, and do anything you want like real userNgoc Pham
@5parkp1ug wouldn't using the force authenticate make tokens useless?fire frost
As stated above, this function can be used to test authenticated endpoint features. force_authenticate bypasses the authentication. If you are looking to perform token based authentication i would suggest you to have a look at credentials method.5parkp1ug
I might be wrong here, but it looks like your problem is not the token auth. If your requests failed authentication, you would get a 401 Unauthorized. Instead you are getting 403 Forbidden which is usually the response for authorization failure, not authentication failure. Check that the token you are using actually has the required permissions to access the endpoint you are requesting.Mad Wombat

2 Answers

3
votes

Just to close this question: after some research, I found out the token on the server was not the same as on the local machine, I just needed to update tokens on both side. The code above works fine.

1
votes

I came here looking for an answer to force_authenticate not working while using a token. To those in the same case, you need to specify both user and token in this manner:

client = APIClient()
client.force_authenticate(user=UserInstance, token=UserInstanceToken)