Ошибка истечения срока действия токена при использовании SimpleJWT TokenVeryifySerializer для возврата пользовательских данных
У меня есть бэкенд API приложение, которое использует DRF и SimpleJWT в качестве движка Auth.
Для фронт-энда React, использующего auth API, требуется конечная точка, которая будет принимать токен доступа, проверять его и возвращать объект токена и связанный с ним объект пользователя.
Я хочу расширить существующий в SimpleJWT TokenVerifySerializer, чтобы сделать это, поскольку он уже содержит логику проверки и черного списка.
Я упираюсь в стену, когда пытаюсь это сделать, так как продолжаю получать Token is invalid or expired error
даже если токен действителен
Любые указания на то, где может быть проблема, будут очень признательны!
Код следующий:
# apiauth/serializer.py
from django.contrib.auth.models import User
from django.apps import apps
from django.contrib.auth.password_validation import validate_password
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenVerifySerializer
from rest_framework_simplejwt.settings import api_settings
from rest_framework_simplejwt.tokens import RefreshToken, SlidingToken, UntypedToken, AccessToken
if api_settings.BLACKLIST_AFTER_ROTATION:
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
token['email'] = user.email
return token
class TokenUserSerializer(TokenVerifySerializer):
token = serializers.CharField()
def validate(self, attrs):
access_token = UntypedToken(attrs["token"])
if (
api_settings.BLACKLIST_AFTER_ROTATION
and apps.is_installed("rest_framework_simplejwt.token_blacklist")
):
jti = access_token.get(api_settings.JTI_CLAIM)
if BlacklistedToken.objects.filter(token__jti=jti).exists():
raise ValidationError("Token is blacklisted")
token = AccessToken(access_token)
user = User.objects.get(access_token['user_id'])
return {user}
class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(
write_only=True, required=True, validators=[validate_password])
password2 = serializers.CharField(write_only=True, required=True)
class Meta:
model = User
fields = ('username', 'password', 'password2')
def validate(self, attrs):
if attrs['password'] != attrs['password2']:
raise serializers.ValidationError(
{"password": "Password fields didn't match."})
return attrs
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
# apiauth/views.py
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.http import JsonResponse
from apiauth.serializer import MyTokenObtainPairSerializer, TokenUserSerializer, RegisterSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.views import TokenVerifyView
from rest_framework import generics
from django.contrib.auth.models import User
from rest_framework.permissions import AllowAny, IsAuthenticated
# Create your views here.
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
class TokenUserView(TokenVerifyView):
serializer_class = TokenUserSerializer
class RegisterView(generics.CreateAPIView):
queryset = User.objects.all()
permission_classes = (AllowAny,)
serializer_class = RegisterSerializer
@api_view(['GET'])
def getRoutes(request):
routes = [
'/apiauth/token/',
'/apiauth/token/user/',
'/apiauth/register/',
'/apiauth/token/refresh/'
]
return Response(routes)
# urls.py
from django.contrib import admin
from django.urls import path, re_path, include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from jobs import views as jobs_views
from items import views as items_views
from contacts import views as contacts_views
schema_view = get_schema_view(
openapi.Info(
title="Basterfield Conductor API",
default_version='v1',
description="Basterfield Conductor API",
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
path('apiauth/', include("apiauth.urls")),
path('jobs/', jobs_views.jobs_list),
path('jobs/<int:job_id>/', jobs_views.jobs_detail),
path('items/', items_views.items_list),
path('items/<int:item_id>/', items_views.items_detail),
path('contacts/', contacts_views.contacts_list),
path('contacts/<int:contact_id>/', contacts_views.contacts_detail),
]