class JWTPairSerializer(JWTBaseSerializer):
    token = serializers.SerializerMethodField()
    refresh = serializers.SerializerMethodField()

    jwt_token_class_name = 'RefreshToken'

    def get_token(self, obj):
        return str(self.get_token_instance().access_token)

    def get_refresh(self, obj):
        return str(self.get_token_instance()) class JWTSlidingSerializer(JWTBaseSerializer):
    token = serializers.SerializerMethodField()

    jwt_token_class_name = 'SlidingToken'

    def get_token(self, obj):
        return str(self.get_token_instance()) class KnoxSerializer(TokenSerializer):
    def get_token(self, obj):
        try:
            from knox.models import AuthToken
        except ImportError:
            warnings.warn(
                'django-rest-knox must be installed for Knox authentication',
                ImportWarning,
            )
            raise

        token_instance, token_key = AuthToken.objects.create(obj)
        return token_key class OAuth1InputSerializer(serializers.Serializer):

    provider = serializers.CharField(required=False)
    oauth_token = serializers.CharField()
    oauth_verifier = serializers.CharField() class OAuth2InputSerializer(serializers.Serializer):

    provider = serializers.CharField(required=False)
    code = serializers.CharField()
    redirect_uri = serializers.CharField(required=False) class TokenSerializer(serializers.Serializer):

    token = serializers.SerializerMethodField()

    def get_token(self, obj):
        token, created = Token.objects.get_or_create(user=obj)
        return token.key class UserJWTSlidingSerializer(JWTSlidingSerializer, UserSerializer):

    def get_token_payload(self, user):
        payload = dict(UserSerializer(user).data)
        payload.pop('id', None)
        return payload class UserKnoxSerializer(KnoxSerializer, UserSerializer):
    pass class UserJWTPairSerializer(JWTPairSerializer, UserSerializer):

    def get_token_payload(self, user):
        payload = dict(UserSerializer(user).data)
        payload.pop('id', None)
        return payload class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = get_user_model()
        # Custom user model may not have some fields from the list below,
        # excluding them based on actual fields
        exclude = [
            field for field in (
                'is_staff', 'is_active', 'date_joined', 'password', 'last_login',
                'user_permissions', 'groups', 'is_superuser',
            ) if field in [mfield.name for mfield in get_user_model()._meta.get_fields()]
        ] class UserTokenSerializer(TokenSerializer, UserSerializer):
    pass
import logging
import warnings
    from urllib.parse import urljoin, urlencode, urlparse  # python 3x
    from urllib import urlencode  # python 2x
    from urlparse import urljoin, urlparse
from django.conf import settings
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.utils.encoding import iri_to_uri
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from social_django.utils import psa, STORAGE
from social_django.views import _do_login as social_auth_login
from social_core.backends.oauth import BaseOAuth1
from social_core.utils import get_strategy, parse_qs, user_is_authenticated, setting_name
from social_core.exceptions import AuthException
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import AllowAny
from requests.exceptions import HTTPError
from .serializers import (
    JWTPairSerializer,
    JWTSlidingSerializer,
    KnoxSerializer,
    OAuth1InputSerializer,
    OAuth2InputSerializer,
    TokenSerializer,
    UserJWTSlidingSerializer,
    UserKnoxSerializer,
    UserJWTPairSerializer,
    UserSerializer,
    UserTokenSerializer,
)
            from knox.auth import TokenAuthentication
            from rest_framework_simplejwt.authentication import JWTAuthentication
        user = self.request.user
        manual_redirect_uri = self.request.auth_data.pop('redirect_uri', None)
        manual_redirect_uri = self.get_redirect_uri(manual_redirect_uri)
        if manual_redirect_uri:
            self.request.backend.redirect_uri = manual_redirect_uri
        elif DOMAIN_FROM_ORIGIN:
            origin = self.request.strategy.request.META.get('HTTP_ORIGIN')
            if origin:
                relative_path = urlparse(self.request.backend.redirect_uri).path
                url = urlparse(origin)
                origin_scheme_host = "%s://%s" % (url.scheme, url.netloc)
                location = urljoin(origin_scheme_host, relative_path)
                self.request.backend.redirect_uri = iri_to_uri(location)
        is_authenticated = user_is_authenticated(user)
        user = is_authenticated and user or None
        # skip checking state by setting following params to False
        # it is responsibility of front-end to check state
        # TODO: maybe create an additional resource, where front-end will
        # store the state before making a call to oauth provider
        # so server can save it in session and consequently check it before
        # sending request to acquire access token.
        # In case of token authentication we need a way to store an anonymous
        # session to do it.
        self.request.backend.REDIRECT_STATE = False
        self.request.backend.STATE_PARAMETER = False

        if self.oauth_v1():
            self.save_token_param_in_session()

        user = self.request.backend.complete(user=user)
        return user

    def save_token_param_in_session(self):
        """
        Save token param in strategy's session.
        This method will allow to use token auth with OAuth1 even if session is not enabled in
        django settings (social_core expects that session is enabled).
        """
        backend = self.request.backend
        session_token_name = backend.name + backend.UNATHORIZED_TOKEN_SUFIX
        session = self.request.strategy.session
        if (
            (isinstance(session, dict) and session_token_name not in session) or
            not session.exists(session_token_name)
        ):
            oauth1_token_param = backend.data.get(backend.OAUTH_TOKEN_PARAMETER_NAME)
            session[session_token_name] = [
                urlencode({
                    backend.OAUTH_TOKEN_PARAMETER_NAME: oauth1_token_param,
                    'oauth_token_secret': backend.data.get('oauth_token_secret')
                })
            ]

    def do_login(self, backend, user):
        """
        Do login action here.
        For example in case of session authentication store the session in
        cookies.
        """

    def set_input_data(self, request, auth_data):
        """
        auth_data will be used used as request_data in strategy
        """
        request.auth_data = auth_data

    def get_redirect_uri(self, manual_redirect_uri):
        if not manual_redirect_uri:
            manual_redirect_uri = getattr(
                settings, 'REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI', None)
        return manual_redirect_uri

    def get_provider_name(self, input_data):
        if self.kwargs.get('provider'):
            return self.kwargs['provider']
        return input_data.get('provider')

    def respond_error(self, error):
        message = error if isinstance(error, str) else ''
        if isinstance(error, Exception):
            if not isinstance(error, AuthException) or LOG_AUTH_EXCEPTIONS:
                self.log_exception(error)
                if hasattr(error, 'response'):
                    try:
                        message = error.response.json()['error']
                        if isinstance(message, dict) and 'message' in message:
                            message = message['message']
                        elif isinstance(message, list) and len(message):
                            message = message[0]
                    except (KeyError, TypeError):
                        pass
        else:
            logger.error(error)
        return Response(data=message, status=status.HTTP_400_BAD_REQUEST)

    def log_exception(self, error):
        err_msg = error.args[0] if error.args else ''
        if getattr(error, 'response', None) is not None:
            try:
                err_data = error.response.json()
            except (ValueError, AttributeError):
                logger.error(u'%s; %s', error, err_msg)
            else:
                logger.error(u'%s; %s; %s', error, err_msg, err_data)
        else:
            logger.exception(u'%s; %s', error, err_msg)


class SocialSessionAuthView(BaseSocialAuthView):
    serializer_class = UserSerializer

    def do_login(self, backend, user):
        social_auth_login(backend, user, user.social_user)

    @method_decorator(csrf_protect)  # just to be sure csrf is not disabled
    def post(self, request, *args, **kwargs):
        return super(SocialSessionAuthView, self).post(request, *args, **kwargs)


class SocialTokenOnlyAuthView(BaseSocialAuthView):

    serializer_class = TokenSerializer