#19 Django-KACAソーシャルログイン


KakaoログインAPIを使用してソーシャルログインを試みます.
ソーシャルログインプロセスは次のとおりです.
  • ユーザは、kakaoログインにより認証コードを取得し、フロントに転送する.
  • フロントは認証コードをKakaoサーバに送信し、Kakao Tokenを受信してバックエンドに送信する.
  • バックエンドからトークンを受信し、KACAサーバに送信してユーザ情報を受信する.
  • は、このユーザ情報がDBにあることを確認した後、サーバトークンをフロントに転送する.
  • 考慮事項
  • プレイヤーの生年月日を保存しようとしたが、基本的には月、日しか提供されていない.
    stringで受信するよりもdate形式で保存する方が拡張性があると思うので、受信したデータを2000-月-日データベースに格納することにしました.
  • にログインするたびに、変更されたプロファイルの写真や名前などのデータベースを更新する必要があります.
    get or create
  • の使用
    フィードバック
  • requests.getを使用する場合はtimeoutを指定したほうがいいです.
  • のテストコードの作成に関するフィードバックは、次の投稿で議論されます.
  • コード#コード#
    import json
    import jwt
    import requests
    from datetime     import datetime
    
    from django.http  import JsonResponse
    from django.views import View
    
    from .models     import User
    from my_settings import SECRET_KEY
    
    class KakaoSigninView(View):
        def get(self, request):
            try:
                access_token = request.headers.get("Authorization")
    
                if not access_token:
                    return JsonResponse({"message" : "NEED_TOKEN"}, status = 400)
    
                response = requests.get(
                    "https://kapi.kakao.com/v2/user/me",
                    headers = {"Authorization" : f"Bearer {access_token}"},
                    timeout = 5
                )
                
                if not response.status == 200:
                    raise ConnectionError
                
                profile_json  = response.json()
    
                kakao_id      = profile_json.get("id")
                kakao_account = profile_json.get("kakao_account")
                name          = kakao_account["profile"]["nickname"]
                thumbnail     = kakao_account["profile"]["thumbnail_image_url"]
                month         = kakao_account["birthday"][0:2]
                day           = kakao_account["birthday"][2:4]
                birthday      = datetime.strptime(f"2000-{month}-{day}", "%Y-%m-%d").date() if kakao_account["birthday_needs_agreement"] else None
    
                user, created = User.objects.get_or_create(
                    kakao     = kakao_id,
                    defaults  = {
                        "name"      : name,
                        "thumbnail" : thumbnail,
                        "birthday"  : "birthday",
                        "is_host"   : False
                })
                
                user.name      = name
                user.thumbnail = thumbnail
                user.birthday  = birthday
                user.save()
    
                token = jwt.encode({"id" : user.id}, SECRET_KEY, algorithm = "HS256")
                return JsonResponse({"message" : "SUCCESS", "token" : token}, status = 200)
    
            except KeyError:
                return JsonResponse({"message" : "KEY_ERROR"}, status = 400)
            
            except ConnectionError:
                return JsonResponse({"message" : "KAKAO_ERROR"}, status = 408)