django

카카오 로그인 (BackEnd)

베스트오버 2023. 6. 15. 09:07

1. 프론트에서 카카오톡에 연결해 코드를 받는다.

 

2. 프론트에서 준 코드로 카카오톡의 token을 받는다.

def get(self, request):
        code = request.GET.get('code')
        
        kakao_token_api = 'https://kauth.kakao.com/oauth/token'
        data = {
            'grant_type' : 'authorization_code',
            'client_id' : KAKAO_REST_API_KEY,
            'redirection_url' : KAKAO_REDIRECT_URL,
            'code' : code,
            'client_secret' : KAKAO_SECRET_KEY,
        }
        headers = {'Content-type': 'application/x-www-form-urlencoded;charset=utf-8'}        
        token_response = requests.post(kakao_token_api, data=data, headers=headers)        
        
        access_token = token_response.json().get('access_token')
        expires_in = token_response.json().get('expires_in')
        refresh_token = token_response.json().get('refresh_token')
        refresh_token_expires_in = token_response.json().get('refresh_token_expires_in')

 

 

3. 카카오톡 토큰으로 유저 정보를 받아 DB에 저장한다.


        user_data = requests.post(
            "https://kapi.kakao.com/v2/user/me",
            headers={
                    "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
                    "Authorization": f"Bearer {access_token}",
                    # "Access-Control-Allow-Origin": "http://127.0.0.1:5500/kakao.html",
            },
        )
        
        user_data = user_data.json()

        email = user_data.get("kakao_account").get("email")
        sns_id = user_data.get('id')
        nickname = user_data.get('properties').get('nickname')
        profile_image = user_data.get('properties').get('profile_image')
        
        kakao_data  = {
            "email" : email,
            "login_type": "kakao",
            "sns_id" : sns_id,
            "nickname" : nickname,
            "profile_image" : profile_image,
            "access_token" : access_token,
            "expires_in" : expires_in,
            "refresh_token" : refresh_token,
            "refresh_token_expires_in" : refresh_token_expires_in,
        }
        
        try:
            kakao_user, created = User.objects.get_or_create(email=email, defaults=kakao_data)
            if created:
                message = "신규 유저 정보 생성!"
                response_status = status.HTTP_200_OK
            else:
                serializer = UserSerializer(kakao_user, data=kakao_data, partial=True)
                if serializer.is_valid():
                    serializer.save()
                    message = "기존 유저 정보 업데이트!"
                    response_status = status.HTTP_200_OK
                else:
                    return Response({"message": {serializer.errors}}, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({"message": "DB 저장 오류입니다."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

4. JWT 토큰을 커스텀해서 발급해준다.

        kakao_user = User.objects.get(email=email)
        
        token = MyTokenObtainPairSerializer.get_token(kakao_user)
        
        # JWT 토큰을 문자열로 변환
        access_token = str(token.access_token)        
        refresh_token = str(token)

        # OpenID connect 사용해요?

        # 오류 등을 try 로 나누고 return이나 response도 나누기
        
        # response에 답기
        response_data = {'message': message, 'access_token': access_token, 'refresh_token': refresh_token}
        return Response(response_data, status=response_status)