Django REST framework gives me csrf token missing when i am logged in for POST requests
i am making an API with django rest framework and django 5.2 when i send a POST request, if i be logged in it gives me an CSRF token missing error. but if i be logged out it gives me response with no error. here are my views for handling user creation and authentication:
@api_view(['POST'])
def signup_view(request):
if not request.user.is_authenticated:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response({"detail": "The user is already logged in."}, status=status.HTTP_403_FORBIDDEN)
@api_view(['POST'])
def login_view(request):
if not request.user.is_authenticated:
user = authenticate(**request.data)
print(request.POST)
if not user:
return Response({"detail": "User authentication failed."}, status=status.HTTP_400_BAD_REQUEST)
login(request, user)
return Response({"detail": "Login was succesful."})
return Response({"detail": "The user is already logged in."}, status=status.HTTP_403_FORBIDDEN)
and here are my views for handling get and post method for the model:
class NoteListView(APIView):
def get(self, request):
notes = Note.objects.filter(author=request.user)
serializer = NoteSerializer(notes, many=True)
data = []
for note in serializer.data:
data.append({'title': note['title']})
return Response(data)
def post(self, request):
serializer = NoteSerializer(data=request.data)
serializer.initial_data['author'] = request.user
print("1")
if serializer.is_valid():
print("2")
serializer.save()
print("3")
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
now i want to know what i have to do for fixing the csrf missing error in this situation.
I developed a project like you and added the following lines to settings.py to fix this problem.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'my_app.custom_authentication.CustomJWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
Then I defined a class called CustomJWTAuthentication. In this class, you need to define a method called authenticate, and its return values will be user and token.
class CustomJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != b'bearer':
return None
.
.
.
.
return (user, token)
Then you need to add the following lines to your views:
class MyView(APIView):
authentication_classes = [CustomJWTAuthentication]
permission_classes = [IsAuthenticated]
Once you do these, auth controls are transferred to you and your CSRF token missing error will gone away.
I also recommend to change your middleware list as below:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # <------------ add this
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]