'Django - DRF - Authentication credentials were not provided. - just in Production. What is the cause?
Problem
During the deployment of my backend API to Heroku trough Docker container I encounter the following error with status 403(Forbidden) whenever I try to access some data where the user has to be authenticated:
{
"detail": "Authentication credentials were not provided."
}
In development everything works as expected.
I am aware of the similar question Django Rest Framework - Authentication credentials were not provided. However here the solution is connected with Apache configuration, which strips the AUTHENTICATION header.
During the debugging of the issue I found out, the AUTHENTICATION header is available for the application, and in fact the token can be obtained and read without any issue.
As a test I have written my own permission class where I have found out, the request.user.is_authenticated line in development gives True but in production gives False with the exact same data and test case.
class AuthOrReadOnly(BasePermission):
def has_permission(self, request, view):
print(request.user.is_authenticated)
if request.method in permissions.SAFE_METHODS:
return True
if request.user.is_authenticated:
return True
return False
SOLUTION to the problem itself
I needed to add authentication_classes = (JWTAuthentication,) for my each APIview class where I need to access authenticated content.
Example:
class RegistrationsForUserView(APIView):
permission_classes = [
permissions.IsAuthenticatedOrReadOnly,
]
authentication_classes = (JWTAuthentication,)
serializer_class = RegistrationSerializerForUser
def get(self, request, pk, format=None):
registrations = Registration.objects.filter(user=pk).order_by(
"tournament__event_date"
)
serializer = RegistrationSerializerForUser(registrations, many=True)
return Response(serializer.data, status.HTTP_200_OK)
In settings.py I have the following regarding REST_FRAMEWORK:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
}
Question
What is the cause of different behavior in production compared to development? What am I missing? In the documentation of DRF the authentication_classes seems to be optional not mandatory. But even if it would be mandatory, I would expect the same behavior in production.
Solution 1:[1]
SOLUTION to the problem itself
I needed to add authentication_classes = (JWTAuthentication,) for my each APIview class where I need to access authenticated content.
Example:
class RegistrationsForUserView(APIView):
permission_classes = [
permissions.IsAuthenticatedOrReadOnly,
]
authentication_classes = (JWTAuthentication,)
serializer_class = RegistrationSerializerForUser
def get(self, request, pk, format=None):
registrations = Registration.objects.filter(user=pk).order_by(
"tournament__event_date"
)
serializer = RegistrationSerializerForUser(registrations, many=True)
return Response(serializer.data, status.HTTP_200_OK)
In settings.py I have the following regarding REST_FRAMEWORK:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MatyasM |
