Как решить ошибку 401 неавторизованный вход в DRF простой jwt вход пользователя
Я создаю DRF API аутентификации для пользователей Abstract Base в моем Django проекте и использую простой JWT. API регистрации и проверки электронной почты работают нормально, но когда я пытаюсь войти в систему, используя учетные данные действительного пользователя, я получаю ошибку 401 несанкционированный доступ.
пользовательская модель пользователя в models.py
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=255, unique=True,db_index=True)
email = models.EmailField(max_length=255, unique=True,db_index=True)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username']
objects = UserManager()
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return{
'refresh':str(refresh),
'access': str(refresh.access_token)
}
Вот мое представление на основе класса логина в views.py
:
class LoginAPIView(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
Вот LoginSerializer в serializers.py
class LoginSerializer(serializers.ModelSerializer):
email = serializers.EmailField(max_length=255, min_length=3)
password = serializers.CharField(max_length=68, min_length=8, write_only=True)
username = serializers.CharField(max_length=255, min_length=3, read_only = True)
tokens = serializers.CharField(max_length=68, min_length=8, read_only = True)
class Meta:
model = User
fields = ['email', 'password', 'username', 'tokens']
def validate(self, attrs):
email = attrs.get('email', '')
password = attrs.get('password', '')
user = auth.authenticate(email=email, password=password)
if not user:
raise AuthenticationFailed('Invalid Credentials, try again!')
if not user.is_active:
raise AuthenticationFailed('Acccount disabled, please contact admin')
if not user.is_verified:
raise AuthenticationFailed('Email is not verified')
return {
'email': user.email,
'username': user.username,
'tokens': user.tokens
}
return super().validate(attrs)
В settings.py
единственными настройками, имеющими отношение к DRF-simple Jwt, являются:
REST_FRAMEWORK = {
'NON_FIELD_ERRORS_KEY': 'error',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
Выдается ошибка "Invalid credentials", означающая, что данные пользователя не существуют, в то время как пользователи на самом деле есть, когда я проверяю базу данных.
Кто-нибудь, пожалуйста, помогите.
Вы хотите исключить представление входа в систему из проверки аутентификации в масштабах проекта, которую вы добавили в settings.py.
class LoginAPIView(generics.GenericAPIView):
permission_classes = ()
authentication_classes = ()
serializer_class = LoginSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
После долгих гуглений и головной боли, я в конце концов снова прочитал простую документацию по Jwt и, как оказалось, ошибка 401 возникает, если пользователь не активен. В моем models.py
выше, по умолчанию, is_verified
и is_active
моего пользователя False
. Представление VerifyEmail
изменило is_verified
на True
после того, как пользователи подтвердили свою электронную почту, но их is_active
остались False
, выдавая ошибку 401.
Моим решением было добавить is_active=True
для случая, когда пользователь проверяет свой email:
Вот VerifyEmail
вид в views.py
class VerifyEmail(views.APIView):
serializer_class = EmailVerificationSerializer
token_param_config = openapi.Parameter('token',in_=openapi.IN_QUERY, description='Description', type=openapi.TYPE_STRING)
@swagger_auto_schema(manual_parameters=[token_param_config])
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token,settings.SECRET_KEY, algorithms=['HS256'])
user = User.objects.get(id=payload['user_id'])
if not user.is_verified:
user.is_verified = True
user.is_active = True # New
user.save()
return Response({'email': 'Succesfully activated'}, status = status.HTTP_200_OK)
except jwt.ExpiredSignatureError as identifier:
return Response({'error': 'Activation Expired'}, status= status.HTTP_400_BAD_REQUEST)
except jwt.exceptions.DecodeError as identifier:
return Response({'error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST)
<