After upgrading to django 5, our test suite started showing odd behavior. We are using DRF's APIClient and authentication does not work as expected anymore. Certain API requests return rest_framework.exceptions.NotAuthenticated with status code 403 (by the way, if someone could explain why this status is 403 and not 401, I'd appreciate).
This is seemingly arbitrary. Among 2 requests to views which are implemented identically in terms of user permissions etc, one returns 403 during testing only. Executing the same calls in Postman does not reproduce the error. Thus, some of the exact same test cases which used to pass under django 4 do not pass anymore under django 5 due to above error. I did not manage to reproduce these cases in a minimal example.
What I did reproduce however, is the following:
client.force_authenticate(user)
client.get(url) # the user does not have permissions. response is 403, as expected
client.force_authenticate(None) # "log out"
user.user_permissions.add(permission)
client.force_authenticate(user)
response = client.get(url) # the now has permissions. response 200 is expected
assert response.status_code == 200 # response status is 403
Package versions are
django==5.0.3
djangorestframework==3.15.0
pytest==7.4.3
pytest-django==4.7.0
I have made a minimal project where this can be observed.
As far as I managed to test it, this unexpected behavior occurs in both django 4 and 5. Am I using the test client incorrectly here?
This behavior is described in the docs:
The solution:
Concerning the
response.status_codereturned for unauthenticated request there is this relevant bit of information in DRF docs:If DEFAULT_AUTHENTICATION_CLASSES are not specified in settings, the default ones are used:
After disabling SessionAuthentication class (or changing the order of authentication classes, BasicAuthentication first), 401 responses are returning for unauthenticated requests.