使用DRF、NextJS和Simple JWT实现仅限电子邮件的OAuth登录

igetnqfo  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(98)

我目前正在做一个使用Django Rest Framework(DRF)和NextJS的项目,并使用Simple JWT处理用户身份验证。
现在,我正在尝试实现OAuth身份验证,特别是一种允许用户仅使用电子邮件登录而无需密码的机制。
以下是现有的类/视图:

class TeacherLoginView(TokenObtainPairView):
    serializer_class = LoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        try:
            user = authenticate(
                request=request,
                email=request.data["email"],
                password=request.data["password"],
            )

            if user != None:
                if not user.is_teacher:
                    return Response(
                        {"is_teacher": "재원생은 {URL}을 통해서 로그인 바랍니다."},
                        status=status.HTTP_401_UNAUTHORIZED,
                    )
                if not user.is_active:
                    return Response(
                        {"is_active": "미승인된 계정입니다. 관리자에게 문의하세요."},
                        status=status.HTTP_401_UNAUTHORIZED,
                    )
                if not ip_check(request, user):
                    return Response(
                        {"error": "학원 외부에서 접속은 불가합니다. 관리자에게 문의하세요."},
                        status=status.HTTP_403_FORBIDDEN,
                    )

            serializer.is_valid(raise_exception=True)

            if user:
                user.last_login = timezone.now()
                user.save()

        except TokenError as e:
            raise InvalidToken(e.args[0])

        return Response(serializer.validated_data, status=status.HTTP_200_OK)

class TeacherKakaoLoginVeiw(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        try:
            code = request.data.get("code")
            access_token = requests.post(
                '''skip'''
            )
            access_token = access_token.json().get("access_token")

            user_data = requests.get(
                '''skip'''
            )
            user_data = user_data.json()
            kakao_account = user_data.get("kakao_account")
            profile = kakao_account.get("profile")
            try:
                user = User.objects.get(email=kakao_account.get("email"))
                TeacherLoginView.post(request, user) # this line is the problem 
                return Response(status=status.HTTP_200_OK)
            except User.DoesNotExist:
                user = User.objects.create(
                    email=kakao_account.get("email"),
                    username=profile.get("nickname"),
                    oauth="kakao",
                    is_teacher = True,
                    is_active = False,
                )
                user.set_unusable_password()  
                user.save()
                TeacherLoginView.post(request, user) # this line is the problem 
                return Response(status=status.HTTP_200_OK)
        except Exception:
            return Response(status=status.HTTP_400_BAD_REQUEST)

TeacherLoginView是一个已经实现的API视图,用于常规的JWT身份验证。
同时,TeacherKakaoLoginView是一个新创建的API视图,用于处理Kakao OAuth认证。
这就是我想要达到的目标:
允许用户通过OAuth(Kakao)只使用他们的电子邮件地址登录确保登录的用户也被颁发JWT令牌我已经搜索了DRF文档和各种论坛,但还没有找到一个符合我试图做的具体例子。我不知道该怎么办,尤其是以下几点:
如何调整现有的TeacherLoginView以使用仅限电子邮件的OAuth登录TeacherKakaoLoginView中需要做哪些更改才能实现所需的OAuth功能并在成功认证后发布JWT令牌任何指针、建议或示例都将非常感谢!
提前感谢您的帮助!

v7pvogib

v7pvogib1#

您可以将TeacherKakaoLoginView修改为:

class TeacherKakaoLoginView(APIView):
       permission_classes = [AllowAny]

       def post(self, request):
           try:
               # OAuth code

               email = kakao_account.get("email")
               try:
                   user = User.objects.get(email=email)
               except User.DoesNotExist:
                   user = User.objects.create(
                       email=email,
                       username=profile.get("nickname"),
                       oauth="kakao",
                       is_teacher=True,
                       is_active=False,
                   )
                   user.set_unusable_password()
                   user.save()

               # Issue JWT tokens
               refresh = RefreshToken.for_user(user)
               return Response({
                   'refresh': str(refresh),
                   'access': str(refresh.access_token),
               })

           except Exception:
               return Response(status=status.HTTP_400_BAD_REQUEST)

相关问题