TIL[79].ソーシャルログインkaka

16452 ワード

1.ソーシャル・ログインとは?


ネット上で他のサービスのアカウントを借りて新しいアカウントを作成または登録することを指す.
Google、フェイスブック、NAVER、KACA、Kindhubなどのルートアカウントで登録することで、サービス利用者の立場で時間短縮などのメリットがあります.サービスプロバイダの立場に立つと、煩雑な加入過程を減らし、消費者の離脱を防ぐことができる.もちろん、ソーシャルアカウントを脱退したり、ハッカーに侵入されたりしてもサービスが利用できないという欠点もありますが、最近では多くのサイトがソーシャルログイン機能を使用しており、お客様がサービスに簡単にアクセスできるようになっています.

2.Kakaoログインプロセスの適用


では、ソーシャルログイン機能の仕組みは何でしょうか.
マカオを例にとると.
Kakaoログインは、Kakaアカウントとアプリケーションを接続し、トークンを取得し、Kaka APIを使用する機能です.

[注意:https://developers.kakao.com/docs/latest/ko/kakaologin/common]

  • まず,適用するウェブサイトアプリケーションをKakaoDeveloperに登録すると,一意のAPI鍵が得られる.

  • フロントエンドでログインボタンを押し、対応する鍵で認証コードを呼び出して転送し、ユーザの同意を得てトークンを取得する.

  • その後受け取った認証コードでKACAサーバにトークンを要求すると、KACAサーバはKACAユーザのトークン(Access Token,Refresh Token)を提供する.

  • フロントから受け取ったKACAユーザトークンをバックエンドに送信すると、バックエンドは対応するトークンを受け取り、KACAにユーザ情報に関するAPIを送信する.

  • KakaoサーバはTokenであることを確認し,ユーザ情報を送信する.

  • ユーザ情報を取得すると、バックエンドはユーザ情報がデータベースにあるかどうかを確認し、存在する場合はトークンを発行してログインします.

  • 新しいユーザ情報の場合、新しいユーザ情報が作成され、トークンが発行されます.
  • 3.コード作成


    以下の記述コードは、上述したアプリケーション中の4〜7個のプロセスをコードとして記述し、フロントを介してpostを介して送信されたtokenを介して、バックグラウンドでKACA APIに必要なユーザ情報を呼び出して登録するものである.

    views.py

    class KakaoSignInView(View):    
        def post(self,request):
            try: 
                access_token   = request.headers.get('Authorization')
                url            = 'https://kapi.kakao.com/v2/user/me'
                headers        = {'Authorization':f'Bearer {access_token}'}
                kakao_response = requests.get(url, headers=headers).json()
                kakao_id       = kakao_response.get('id')
                kakao_account  = kakao_response.get('kakao_account') 
                email          = kakao_account.get('email',None)
                kakao_profile  = kakao_account.get('profile')
                name           = kakao_profile.get('nickname')
            
                if Account.objects.filter(email=email).exists():
                    user  = Account.objects.get(email=email)
                    token = jwt.encode({'id':user.id},SECRET,algorithm=ALGORITHM)
                    token = token.decode('utf-8')
                    
                    return JsonResponse(
                        {'token'  : token,
                        'message' : 'SUCCESS'}, 
                        status=200
                    )
            
                else:
                    Account.objects.create(
                        kakao_id = kakao_id,
                        email = email,
                        name = name
                    )              
    
                    token = jwt.encode({'email':email},SECRET,algorithm=ALGORITHM)
                    token = token.decode('utf-8')
                    
                    return JsonResponse(
                        {'token'  : token,
                        'message' : 'SUCCESS'}, 
                        status=200
                    )
            
            except IntegrityError:
                        return JsonResponse(
                            {'message':'ALREADY_EXISTS'},
                            status = 400 
                        )
    
            except KeyError:
                return JsonResponse({'message':'KEY_ERROR'},status = 400)      

    tests.py

    class KakaoSignInTest(TestCase):
        
        def setUp(self):
            Account.objects.create(
                kakao_id = '1499',
                name     = 'hong',
                email    = '[email protected]',
            ) 
        def teardown(self):
            Account.objects.all.delete()
        
        @patch('account.views.requests')
        def test_kakao_sign_in(self,mocked_requests):
            client = Client()
            
            class MockedResponse:
                def json(self):
                    return{
                        'id'      : 1499, 
                        'kakao_account': { 
                        'profile': {
                            'nickname': 'hong',
                        },'email': '[email protected]'}
                    }
                               
            mocked_requests.get = MagicMock(return_value = MockedResponse())
            
            test = {
                'kakao_id' : 1499, 
                'email'    : '[email protected]',
                'name'     : 'hong',
                }
    
            response = client.post('/account/emailcheck/kakaosignin',json.dumps(test), **{'Authorization':'1234', 'content_type':'application/json'})
            self.assertEqual(response.status_code,200)