Search code examples
pythondjango-rest-frameworkjwtdjango-rest-framework-jwt

how to generate rest_framework_jwt token in the login process


I'm trying to implement django-rest-framework-jwt for authentication. I did all what jwt tutorials said (adding the setting, url and curl testing). and I did successfully obtain the token using 127.0.0.1:8000/api/auth/token/ in the browsable api.

but what I don't get is how to generate the token in the login process. My guess is to generate it in the LoginSerializer maybe? (or I misunderstood the concept!)

Here's what I have:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

# project/urls.py
url(r'^api/auth/token/', obtain_jwt_token),

login serializer and view:

class UserLoginSerializer(ModelSerializer):
    token = CharField(allow_blank=True, read_only=True)
    class Meta:
        model = User
        fields = ('username', 'password', 'token')

    def validate(self, data):
        username = data.get('username',None)
        password = data['password']

        user = authenticate(username=username, password=password)
        if not user or not user.is_active:
            raise ValidationError("Invalid username/password.")

        # generate jwt token ??
        # data['token'] = generated jwt token??

        return data


class UserLoginAPIView(APIView):
    permission_classes = [AllowAny]
    serializer_class = UserLoginSerializer

    def post(self, request, *args, **kwargs):
        data = request.data
        serializer = UserLoginSerializer(data=data)
        if serializer.is_valid(raise_exception=True):
            new_data = serializer.data
            return Response(new_data, status=HTTP_200_OK)
        return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

So what do I have to do?


Solution

  • Here is what i did.

    from rest_framework_jwt.settings import api_settings
    
    
    class LoginView(APIView):
        '''
        Post call for user login.
        '''
    
        def post(self, request, format=None):
            serializer = LoginSerializer(data=request.data)
    
            if serializer.is_valid():
    
                # Check if user has valid credentials and return user instance else None
                user = authenticate(username=serializer.validated_data['username'],
                                    password=serializer.validated_data['password'])
    
                if user is not None:
    
                    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
                    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    
                    payload = jwt_payload_handler(user)
                    token = jwt_encode_handler(payload)
    
                    return Response({'msg':'Login successful', 'token': token, 'is_login_success': True}, status=status.HTTP_200_OK)
                else:
                    return Response({'msg': 'Credentials are not valid!'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    

    But you dont have to do that since your 127.0.0.1:8000/api/auth/token/ is doing pretty exactly the same, unless you want to record something before logging in.

    If you want more information how obtain_jwt_token view works, its JSONWebTokenSerializer will help you.