1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
from typing import Optional
from django.utils.module_loading import import_string
from rest_framework import generics, status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import BaseSerializer
from .authentication import AUTH_HEADER_TYPES
from .exceptions import InvalidToken, TokenError
from .settings import api_settings
class TokenViewBase(generics.GenericAPIView):
permission_classes = ()
authentication_classes = ()
serializer_class: Optional[type[BaseSerializer]] = None
_serializer_class = ""
www_authenticate_realm = "api"
def get_serializer_class(self) -> type[BaseSerializer]:
"""
If serializer_class is set, use it directly. Otherwise get the class from settings.
"""
if self.serializer_class:
return self.serializer_class
try:
return import_string(self._serializer_class)
except ImportError as e:
msg = f"Could not import serializer '{self._serializer_class}'"
raise ImportError(msg) from e
def get_authenticate_header(self, request: Request) -> str:
return '{} realm="{}"'.format(
AUTH_HEADER_TYPES[0],
self.www_authenticate_realm,
)
def post(self, request: Request, *args, **kwargs) -> Response:
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0]) from e
return Response(serializer.validated_data, status=status.HTTP_200_OK)
class TokenObtainPairView(TokenViewBase):
"""
Takes a set of user credentials and returns an access and refresh JSON web
token pair to prove the authentication of those credentials.
"""
_serializer_class = api_settings.TOKEN_OBTAIN_SERIALIZER
token_obtain_pair = TokenObtainPairView.as_view()
class TokenRefreshView(TokenViewBase):
"""
Takes a refresh type JSON web token and returns an access type JSON web
token if the refresh token is valid.
"""
_serializer_class = api_settings.TOKEN_REFRESH_SERIALIZER
token_refresh = TokenRefreshView.as_view()
class TokenObtainSlidingView(TokenViewBase):
"""
Takes a set of user credentials and returns a sliding JSON web token to
prove the authentication of those credentials.
"""
_serializer_class = api_settings.SLIDING_TOKEN_OBTAIN_SERIALIZER
token_obtain_sliding = TokenObtainSlidingView.as_view()
class TokenRefreshSlidingView(TokenViewBase):
"""
Takes a sliding JSON web token and returns a new, refreshed version if the
token's refresh period has not expired.
"""
_serializer_class = api_settings.SLIDING_TOKEN_REFRESH_SERIALIZER
token_refresh_sliding = TokenRefreshSlidingView.as_view()
class TokenVerifyView(TokenViewBase):
"""
Takes a token and indicates if it is valid. This view provides no
information about a token's fitness for a particular use.
"""
_serializer_class = api_settings.TOKEN_VERIFY_SERIALIZER
token_verify = TokenVerifyView.as_view()
class TokenBlacklistView(TokenViewBase):
"""
Takes a token and blacklists it. Must be used with the
`rest_framework_simplejwt.token_blacklist` app installed.
"""
_serializer_class = api_settings.TOKEN_BLACKLIST_SERIALIZER
token_blacklist = TokenBlacklistView.as_view()
|