Home > Software design >  How to handle login API in Django web app
How to handle login API in Django web app

Time:11-15

I have already implemented a list of shop API including user api, product api etc using Rest Framework. User api include basic login/logout/register methods. Login require username and password, so API call looks like requests.post('api/api_user/login', {username='name', password='password'}). Post method returns auth token like following: Post result

The issue is how can i handle @login_required in web app using my API. The idea of login is intuitive, i can send post request and get token which can be stored in cookies, but Django use it's own authentication system to handle user login on viewes (@login_required decorator), so i left with an idea to get token from cookies in every request and check it for correctness, but is it right way to do such things? I'm looking for examples or suggestions how this thing should be implemented.

My auth api implementation is following:

from django.contrib.auth import login
from knox.views import LoginView as KnoxLoginView, LogoutView as KnoxLogoutView
from rest_framework import permissions, generics, status
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.response import Response

from .serializers import UserSerializer, RegisterSerializer, ChangePasswordSerializer


class RegisterAPI(generics.CreateAPIView):
    serializer_class = RegisterSerializer
    permission_classes = (permissions.AllowAny,)
    http_method_names = ['post']

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response({"user": UserSerializer(user, context=self.get_serializer_context()).data}, status=status.HTTP_200_OK)


class LoginAPI(KnoxLoginView):
    serializer_class = AuthTokenSerializer
    permission_classes = (permissions.AllowAny,)
    http_method_names = ['post']

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginAPI, self).post(request, format=None)


class ChangePasswordAPI(generics.UpdateAPIView):
    serializer_class = ChangePasswordSerializer
    permission_classes = (permissions.IsAuthenticated,)
    http_method_names = ['put']

    def get_object(self, queryset=None):
        obj = self.request.user
        return obj

    def update(self, request, *args, **kwargs):
        self.object = self.get_object()
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            if not self.object.check_password(serializer.data.get("old_password")):
                return Response({"detail": "Wrong old password"}, status=status.HTTP_400_BAD_REQUEST)
            self.object.set_password(serializer.data.get("new_password"))
            self.object.save()
            return Response({'detail': 'Password updated successfully'}, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class LogoutAPI(KnoxLogoutView):
    http_method_names = ['post']

CodePudding user response:

By default, Django requires session authentication. Since you are generating token manually, you have to authenticate it in every API manually. For this you have to write the custom authenticate method which decodes the token and checks the details.

Or

As per DRF documentation, you can use the default authenticated permission class if you have used the DRF authentication.

CodePudding user response:

Django authentication can be used to perform queiries in following way, but before you should login and get session id and token.

ses_id = request.session.session_key
token = get_token(request)
cookies = {'csrftoken': token, 'sessionid': ses_id}
response = requests.get('http://127.0.0.1:8000/api/api_product/product_types/', cookies=cookies)
  • Related