Django - DRF - Учетные данные для аутентификации не были предоставлены. - только в Production. В чем причина?
Проблема
Во время развертывания моего backend API на Heroku через контейнер Docker я сталкиваюсь со следующей ошибкой со статусом 403(Forbidden), когда я пытаюсь получить доступ к некоторым данным, где пользователь должен быть аутентифицирован:
{
"detail": "Authentication credentials were not provided."
}
В разработке все работает так, как ожидалось.
Я знаю о похожем вопросе Django Rest Framework - Authentication credentials were not provided. Однако здесь решение связано с конфигурацией Apache, которая удаляет заголовок AUTHENTICATION.
Во время отладки проблемы я обнаружил, что заголовок AUTHENTICATION доступен для приложения, и на самом деле токен может быть получен и прочитан без каких-либо проблем.
В качестве теста я написал свой собственный класс разрешения, где я обнаружил, что строка request.user.is_authenticated в разработке дает True, а в производстве дает False с точно такими же данными и тестовым примером.
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
РЕШЕНИЕ самой проблемы
Мне нужно добавить authentication_classes = (JWTAuthentication,) для каждого класса APIview, где мне нужно получить доступ к аутентифицированному содержимому.
Пример:
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)
В settings.py у меня есть следующее относительно REST_FRAMEWORK:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
}
Вопрос
В чем причина различного поведения в производстве по сравнению с разработкой? Что я упускаю? В документации DRF authentication_classes кажется опциональным, а не обязательным. Но даже если бы он был обязательным, я бы ожидал такого же поведения в производстве.
РЕШЕНИЕ самой проблемы
Мне нужно добавить authentication_classes = (JWTAuthentication,) для каждого класса APIview, где мне нужно получить доступ к аутентифицированному содержимому.
Пример:
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)
В settings.py у меня есть следующее относительно REST_FRAMEWORK:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
}