Generating and Authenticating using JWT

One can implement generating and authenticating using JWT. Below is the AuthTokenManager implementation for JWT:

class AuthJWTManager(AbstractAuthTokenManager):

    def get_authentication_class(self) -> Type[BaseAuthentication]:
        return JWTAuthentication

    def get_app_names(self) -> Sequence[str]:
        return [
            'tests.testapps.custom_authtokens',  # update with your Django app
        ]

    def provide_token(self, user: 'AbstractBaseUser') -> AuthToken:
        encoded_jwt = jwt.encode(
            {"user_id": user.pk},
            settings.SECRET_KEY,
            algorithm=JWTAuthentication.ALGORITHM,
        )
        return AuthToken(encoded_jwt)

    def revoke_token(
            self, user: 'AbstractBaseUser', *,
            token: Optional[AuthToken] = None) -> None:
        raise AuthTokenNotRevoked()

And here is the Django REST Framework authentication class:

class JWTAuthentication(BaseAuthentication):
    ALGORITHM = "HS256"

    def authenticate(self, request):
        """
        Returns a `User` if a correct username and password have been supplied
        using HTTP Basic authentication.  Otherwise returns `None`.
        """
        auth = get_authorization_header(request).split()

        if not auth or auth[0].lower() != b'bearer':
            return None

        if len(auth) == 1:
            msg = _('Invalid authorization header. No credentials provided.')
            raise AuthenticationFailed(msg)
        if len(auth) > 2:
            msg = _(
                'Invalid authorization header. Credentials string should not'
                ' contain spaces.'
            )
            raise AuthenticationFailed(msg)

        encoded_jwt = auth[1]

        try:
            jwt_data = jwt.decode(
                encoded_jwt,
                settings.SECRET_KEY,
                algorithms=[self.ALGORITHM],
            )
        except jwt.ExpiredSignatureError:
            msg = _('Expired JWT.')
            raise AuthenticationFailed(msg) from None
        except jwt.InvalidTokenError:
            msg = _('Invalid JWT payload.')
            raise AuthenticationFailed(msg) from None

        try:
            user_id = jwt_data["user_id"]
        except KeyError:
            msg = _('Missing user info in JWT.')
            raise AuthenticationFailed(msg) from None

        user_class = get_user_model()
        try:
            user = user_class.objects.get(pk=user_id)
        except user_class.DoesNotExist:
            msg = _('User not found.')
            raise AuthenticationFailed(msg) from None

        return (user, encoded_jwt)