Django rest framework с simplejwt получает ответ 200 ok даже для недействительных токенов
Я использую django-rest-framework, djoser и simplejwt для создания token auth для учетных записей пользователей.
Я могу создать учетную запись, активировать и войти в систему с помощью Postman. Но по какой-то причине у меня возникла проблема с конечными точками /refresh и /verify. У меня также есть проблемы с /logout и /auth/me, но я предполагаю, что если я смогу исправить /refresh и /verify конечные точки, то другие тоже исправятся.
Вот тестовые урлы и методы, которые я использую с Postman
POST http://localhost:8000/api/users/
После этого я захожу в свою электронную почту и копирую uid и token
POST http://localhost:8000/api/users/activation/
введите uid и token в тело запроса
POST http://localhost:8000/api/jwt/create/
убедитесь, что email и pw указаны в теле письма, и нажмите кнопку «Отправить», получите обновление и токены доступа
POST http://localhost:8000/api/jwt/refresh/
введите токен обновления следующим образом {«refresh»: «kjlsjfdlskldjfls...."}
Здесь я ввожу дополнительный символ в конце, чтобы сделать его недействительным токеном, но я все равно получаю 200 ok вместе с токеном доступа, почему?
POST http://localhost:8000/api/jwt/verify
введите {«token»: «jaslkfjsld...."}
снова ввожу дополнительный символ, чтобы сделать токен недействительным, но все равно получаю 200 ok с токеном доступа, почему?
Я просмотрел весь код, который, как я полагаю, является соответствующим, и не могу понять, где я ошибаюсь?
Это моя пользовательская модель пользователя с DRF:
class UserAccount(AbstractBaseUser, PermissionsMixin): **model.py**
id = f'{models.UUIDField(primary_key=True, default=RandomUUID, editable=False)}'
first_name = models.CharField(blank=True, max_length=255)
last_name = models.CharField(blank=True, max_length=255)
email = models.EmailField(unique=True, max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
objects = UserAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
def __str__(self):
return self.email
Это мой UserAccountManager: manager.py
class UserAccountManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError("Users must have an email address")
email = self.normalize_email(email)
email = email.lower()
user = self.model(
email=email,
**kwargs
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **kwargs):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
**kwargs
)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
Это мои пользовательские представления, views.py
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
class CustomTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
if response.status_code == 200:
access_token = response.data.get('access')
refresh_token = response.data.get('refresh')
response.set_cookie(
'access',
access_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
response.set_cookie(
'refresh',
refresh_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
return response
class CustomTokenRefreshView(TokenRefreshView):
def post(self, request, *args, **kwargs):
refresh_token = request.COOKIES.get('refresh')
if refresh_token:
request.data['refresh'] = refresh_token
response = super().post(request, *args, **kwargs)
if response.status_code == 200:
access_token = response.data.get('access')
response.set_cookie(
'access',
access_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
return response
class CustomTokenVerifyView(TokenVerifyView):
def post(self, request, *args, **kwargs):
access_token = request.COOKIES.get('access')
if access_token:
request.data['token'] = access_token
return super().post(request, *args, **kwargs)
class LogoutView(APIView):
def post(self, request, *args, **kwargs):
response = Response(status=status.HTTP_204_NO_CONTENT)
response.delete_cookie('access')
response.delete_cookie('refresh')
return response
Это адреса для создания, обновления, проверки и выхода
urlpatterns = [
path('jwt/create/', CustomTokenObtainPairView.as_view()),
path('jwt/refresh/', CustomTokenRefreshView.as_view()),
path('jwt/verify/', CustomTokenVerifyView.as_view()),
path('logout/', LogoutView.as_view()),
]
А этот authentication.py используется для httponly cookies mgmt:
from django.conf import settings
from rest_framework_simplejwt.authentication import JWTAuthentication
class CustomJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
try:
header = self.get_header(request)
if header is None:
raw_token = request.COOKIES.get(settings.AUTH_COOKIE)
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
return self.get_user(validated_token), validated_token
except:
return None