Django ⎮ 카카오 소셜 로그인 & 회원가입 API

Chris-Yang·2021년 10월 24일
2

Django

목록 보기
3/7
post-thumbnail

> Flow

  1. FE로부터 kakao token을 받습니다.
  2. 받은 kakao token을 이용해 kakao로부터 유저정보 받아옵니다.
  3. 받아온 유저정보를 통해 user db를 조회하여 회원인지 아닌지 확인합니다.
    3-1. 회원이 아니면 회원가입을 시킵니다.
  4. user db에서 등록된 유저 정보를 가져옵니다.
  5. 회원인 유저의 id를 가져와 jwt로 암호화 시켜 토큰을 발행합니다.



> Code

import jwt
import requests
from json.decoder import JSONDecodeError

from django.http  import JsonResponse
from django.views import View

from users.models import User
from my_settings  import SECRET_KEY, ALGORITHMS

class KakaoLogin(View):
    def get(self, request):
        try: 
            # kakao token 받기 / 유효성 검사를 합니다.
            token = request.headers.get('Authorization')

            if token == None:
                return JsonResponse({'messsage': 'INVALID_TOKEN'}, status=401)
                
	    # kakao token을 다시 kakao로 보내서 유저 정보를 받아옵니다.
            kakao_account = requests.get('https://kapi.kakao.com/v2/user/me', \
            	headers = {'Authorization': f'Bearer {token}'}).json()

	    # 받아온 kakao 유저정보중 id가 db에 있는지 확인합니다.
            if not User.objects.filter(kakao_id=kakao_account['id']).exists():
               # 유저 정보가 없으면 회원가입 되도록 합니다.
               user = User.objects.create(
                    kakao_id = kakao_account['id'],
                    email    = kakao_account['kakao_account']['email']
                    )

	    # kakao id를 통해 db에서 해당 유저 정보를 가져옵니다.
            user = User.objects.get(kakao_id=kakao_account['id'])

	    # 유저의 id를 jwt를 통해 암호화하여 token에 실어줍니다.
            access_token = jwt.encode({'user_id': user.id}, SECRET_KEY, algorithm=ALGORITHMS)

            return JsonResponse({'access_token': access_token}, status=201)

        except KeyError:
            return JsonResponse({'message': 'KEY_ERROR'}, status=400)
        
        except JSONDecodeError:
            return JsonResponse({'message': 'JSON_DECODE_ERROR'}, status=400)

        except jwt.DecodeError:
            return JsonResponse({'message': 'JWT_DECODE_ERROR'}, status=400)

        except ConnectionError:
            return JsonResponse({'message': 'CONNECTION_ERROR'}, status=400)



> Divide and Conquer

▶︎ kakao token을 통한 user 정보 가져오기

kakao_account = requests.get('https://kapi.kakao.com/v2/user/me', \
            	headers = {'Authorization': f'Bearer {token}'}).json()

FE로부터 받아온 kakao token이 있으면 kakao REST API를 통해
유저정보를 가져올 수 있습니다.

🥕 kakao developers 카카오 로그인 REST API 사용자정보 가져오기 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info



▶︎ kakao 유저정보로 db 조회

if not User.objects.filter(kakao_id=kakao_account['id']).exists():
   user = User.objects.create(
        kakao_id = kakao_account['id'],
        email    = kakao_account['kakao_account']['email']
        )

kakao에서 가져온 유저정보를 통해 db에 접근하여 일치하는 kakao 정보가 있는지
조회하고 없는 경우 정책에 따른 유저 정보를 db에 저장시켜 회원가입으로 연결시킵니다.

유저가 카카오 로그인을 시도하는 것 자체가 해당 사이트 회원가입에 대한 의지가
있는 것이기 때문에 자연스럽게 회원가입이 되도록 하였습니다.



▶︎ 유저정보 암호화 및 토큰 생성

user = User.objects.get(kakao_id=kakao_account['id'])

access_token = jwt.encode({'user_id': user.id}, SECRET_KEY, algorithm=ALGORITHMS)

return JsonResponse({'access_token': access_token}, status=201)

카카오 로그인으로 가입한 회원은 kakao id를 가져와 저장하였기 때문에
해당 id로 회원정보를 가져오도록 하였습니다.

만약 사이트 자체 회원가입 기능이 있다면 그냥 email로 회원조회 기준을
통일하는 것도 좋을 것 같습니다.

조회된 회원정보를 바탕으로 유저의 id를 가져와 jwt를 통해 암호화 및
토큰을 생성하여 FE에게 전송해 주게 됩니다.

profile
sharing all the world

0개의 댓글