[django] Kakao Login API

이번 프로젝트에서 소셜 로그인을 구현해보기로 하여 카카오로그인 API를 만들어 본 경험을 기록으로 남긴다.

1. 카카오 로그인 시퀀스

https://developers.kakao.com/
에서 문서탭의 카카오 로그인 항목을 보면 카카오 로그인을 구현하는 방법이 안내되어있다. 장고의 경우 REST API 를 선택하여 보면 된다.


출처: https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#before-you-begin

위의 표에서 보듯 로그인 절차는 3단계로 크게 나누어 볼 수 있다. 실질적으로 Kakao Auth Server와 통신하는 것은 stpe2 토큰받기 까지이기이고 step3은 토큰을 통해 사용자 정보를 저장하거나 가공하는 것이기 때문에 각자의 상황에 맞게 활용하면 되겠다.

나는 Service Server의 입장에서 Service Client에서 Kakao Auth Server에 로그인 요청을 한 후 302 Redirect URI로 인가 코드 전달을 받는 부분부터 구현하였다.

2. 사전 설정

카카오 로그인을 하기위해서는 플랫폼 등록, 카카오 로그인 활성화, Redirect URI등록, 동의항목 결정 등의 사전 설정이 필요하다.
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-token-info
위 주소를 참고하여 사전 설정을 할 수 있다. 여기서 Redirect URI는 위의 시퀀스에서 6번에 해당하는 인가 코드를 받을 URI라고 생각하면 된다. 아직 로컬에서 개발중인 경우 http://localhost:8000 과 같이 설정하면 되겠다.
장고를 기준으로 말하자면 인가코드는
'Redirect_URI?code='auth_code'
의 형식으로 Redirect URI 주소로 query parameter로 들어오기 때문에 인가 코드를 받아서 토큰을 요청하는 View의 주소로 설정할 경우 바로 인가 코드를 받아서 활용할 수 있다.

3. 코드작성

import json, re, bcrypt, jwt, requests

from django.shortcuts import render, redirect
from django.views     import View
from django.http      import JsonResponse
from django.conf      import settings

from users.models     import User


class KakaoAPI:
    def __init__(self, authorization_code):
        self.authorization_code = authorization_code
        self.token_url = "https://kauth.kakao.com/oauth/token"
        self.user_url  = "https://kapi.kakao.com/v2/user/me"
        self.redirect_url = "http://local:8000/users/kakao/callback"
        
    def get_access_token(self):
        data = {
            'grant_type': 'authorization_code',
            'client_id': settings.KAKAO_APP_KEY,
            'redirect_uri': self.redirect_url,
            'code': self.authorization_code
        }
        response     = requests.post(self.token_url, data)
        access_token = response.json()['access_token']
        return access_token
        
    def get_user_information(self, access_token):
        header = {
            "Authorization" : f'Bearer {access_token}',
            "Content-type"  : "application/x-www-form-unlencoded;charset=utf-8"
        }
        
        user_info = requests.get(self.user_url, headers = header)

        return user_info.json()
 
class KakaoSignView(View):
    def get(self, request):
        auth_code    = request.GET.get('code')
        access_token = KakaoAPI(auth_code).get_access_token()
        user_info    = KakaoAPI(auth_code).get_user_information(access_token)
        kakao_id  = user_info['id']
        nickname  = user_info['kakao_account']['profile']['nickname']
        email     = user_info['kakao_account']['email']
        
        user, created = User.objects.get_or_create(
            kakao_id = kakao_id, defaults = {'name' : nickname, 'email':email}
            )   
             
        token = jwt.encode({'id':user.id}, settings.SECRET_KEY, algorithm=settings.ALGORITHM)

        if created:
            return JsonResponse({"message" : "CREATED", "token" : token}, status = 201)
        
        return JsonResponse({"message" : "SIGNED_IN", "token" : token}, status = 200)

좋은 웹페이지 즐겨찾기