Issue
I am working on custom authentication in DRF. User should send 3 fields (phone, email, password).
I was following this answer Adding custom user authentication to django-rest-framework-simple-jwt
(I was overriding TokenObtainPairSerializer
and TokenObtainPairView
)
I was using this source code https://github.com/jazzband/djangorestframework-simplejwt/blob/master/rest_framework_simplejwt/serializers.py
Problem: for the request below I received an empty response {}
but expected tokens or error message
{
"email": "[email protected]",
"password": "admin123456",
"phone_number": "123132"
}
My code: views.py
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
serializers.py
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
username_field = CustomUser.USERNAME_FIELD
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[self.username_field] = serializers.CharField()
self.fields['password'] = PasswordField()
self.fields['phone_number'] = serializers.CharField() # authentication requires 3 fields
def validate(self, attrs):
authenticate_kwargs = {
self.username_field: attrs[self.username_field],
'password': attrs['password'],
'phone_number': attrs['phone_number']
}
try:
authenticate_kwargs["request"] = self.context["request"]
except KeyError:
pass
self.user = authenticate(**authenticate_kwargs)
if not api_settings.USER_AUTHENTICATION_RULE(self.user):
raise exceptions.AuthenticationFailed(
self.error_messages["no_active_account"],
"no_active_account",
)
return {}
Solution
Let’s try to login and generate a token manually:
serializers.py
from rest_framework import serializer
class LoginUserSerializer(serializers.Serializer):
email = serializers.EmailField()
phone_number = serializers.CharField()
password = serializers.CharField(write_only=True)
views.py
from django.contrib.auth import authenticate
from rest_framework import status, serializers
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken
class LoginUserApi(APIView):
def post(self, request):
serializer = LoginUserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data # Fetch the data form serializer
user = authenticate(email=data['email'], password=data['password']) # check for email and password
if not user or user.phone_number != data['phone_number']: # check for phone
raise serializers.ValidationError({'detail':'Incorrect email, phone, or password'})
# Generate Token
refresh = RefreshToken.for_user(user)
return Response(
{
'access': str(refresh.access_token),
'refresh': str(refresh)
}
, status=status.HTTP_200_OK
)
How to create tokens manually from Simple JWT docs
Answered By – Mohamed Hamza
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0