[DRF] 카카오 소셜로그인 (JWT)

김재연·2022년 7월 18일
1

Watti

목록 보기
3/10
post-thumbnail

로직은 구글 소셜로그인이랑 진짜 똑같다. 한번 해봤으니까 이론적인 것도 한번 정리해보려고 한다. (카카오 공식문서에 잘 설명돼있길래 겸사겸사)

초기세팅

카카오 개발자 애플리케이션에서 애플리케이션을 추가한다.

내 애플리케이션 > 제품설정 > 카카오 로그인 으로 가서 활성화 설정을 ON으로 바꿔준다.

redirect URI를 등록하고, (콜백함수 url)

내 애플리케이션 > 제품설정 > 카카오 로그인 > 동의항목 으로 가서 카카오 로그인으로 서비스를 시작할 때 동의 받는 항목을 설정한다.

  • 필수 동의 : 카카오 로그인 시 사용자가 필수로 동의해야함
  • 이용 중 동의 : 카카오 로그인 시 동의를 받지 않고, 항목이 필요한 시점에 동의를 받음

다른 기타 라이브러리 설치나 settings.py는 구글 소셜로그인 포스팅이랑 동일

Client_id, Secret key 및 사이트 설정

# settings.py

INSTALLED_APPS = [
	...
    'allauth.socialaccount.providers.kakao',
]
# .env
SOCIAL_AUTH_KAKAO_CLIENT_ID = "내 앱의 REST API 키"
SOCIAL_AUTH_KAKAO_SECRET = "앱 ID"

admin 페이지에서 카카오 ID, 시크릿 키를 등록한다.

카카오 로그인 API 작동 플로우

이제 코드를 쓸 시간인데 그 전에 이거부터 보자.

요약버전

이 순서에 맞춰서 코드를 설명하도록 하겠당.

Step 1. 인가 코드 받기

KAKAO_CALLBACK_URI = BASE_URL + 'api/user/kakao/callback/'

def kakao_login(request):
    client_id = os.environ.get("SOCIAL_AUTH_KAKAO_CLIENT_ID")
    return redirect(f"https://kauth.kakao.com/oauth/authorize?client_id={client_id}&redirect_uri={KAKAO_CALLBACK_URI}&response_type=code&scope=account_email")

카카오 로그인창을 띄우고, 사용자가 카카오 계정으로 로그인을 하면 인증 코드를 받아오는 함수다. 맨 뒤에 scope=account_email추가 항목 동의 받기를 위한 부분인데, 서비스에 회원가입하려면 이메일이 꼭 필요한데 이메일은 제공 동의를 해줘야 받아올 수 있는 정보이기 때문에(심지어 카카오톡 일정 버전부터는 이메일 없이도 카카오 계정 생성이 된다고 한다....) 이메일 동의를 받기 위해 넣은 것이다.

Step 2. 토큰 받기

def kakao_callback(request):
    client_id = os.environ.get("SOCIAL_AUTH_KAKAO_CLIENT_ID")
    code = request.GET.get("code")

    # code로 access token 요청
    token_request = requests.get(f"https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id={client_id}&redirect_uri={KAKAO_CALLBACK_URI}&code={code}")
    token_response_json = token_request.json()

    # 에러 발생 시 중단
    error = token_response_json.get("error", None)
    if error is not None:
        raise JSONDecodeError(error)

    access_token = token_response_json.get("access_token")
    ...

위에서 받아온 인증 코드로 access token을 받아온다.

Step 3. 사용자 로그인 처리

def kakao_callback(request):
	...
	# access token으로 카카오톡 프로필 요청
    profile_request = requests.post(
        "https://kapi.kakao.com/v2/user/me",
        headers={"Authorization": f"Bearer {access_token}"},
    )
    profile_json = profile_request.json()

    kakao_account = profile_json.get("kakao_account")
    email = kakao_account.get("email", None) # 이메일!

    # 이메일 없으면 오류 => 카카오톡 최신 버전에서는 이메일 없이 가입 가능해서 추후 수정해야함
    if email is None:
        return JsonResponse({'err_msg': 'failed to get email'}, status=status.HTTP_400_BAD_REQUEST)
	...

앞에서 받아온 access token으로 카카오 사용자 프로필을 받아와서 이메일을 뽑아낸다. 추출해낸 이메일로 서비스에 회원가입/로그인/jwt토큰 발급하는 코드는 구글 소셜로그인과 동일.

참고로 카카오 프로필은 다음과 같은 형태로 받아와진다. (사용자가 이메일 동의항목에 동의하지 않은 경우)

{
  "id": 1633204891,
  "connected_at": "2021-02-18T06:13:55Z",
  "properties": {
    "${CUSTOM_PROPERTY_KEY}": "${CUSTOM_PROPERTY_VALUE}",
    ...
  },
  "kakao_account": {
    "profile_needs_agreement": false,
    "profile": {
      "nickname": "춘식이",
      "thumbnail_image_url": "http://k.kakaocdn.net/dn/DCjQu/btqti3A1gEc/zgip1O4JmSnG7CDfmKtTO2/img_110x110.jpg",
      "profile_image_url": "http://k.kakaocdn.net/dn/DCjQu/btqti3A1gEc/zgip1O4JmSnG7CDfmKtTO2/img_640x640.jpg",
      "is_default_image": false
    },
    "email_needs_agreement": true       // 이메일 동의 항목에 사용자 동의 필요
  }
}

email_needs_agreementtrue라는 것은 사용자가 동의하면 이메일 정보를 받을 수 있는 상태를 의미하는 것으로, (❗이메일을 주겠다는 뜻이 아님❗) 위에서 서술한 추가 항목 동의 받기를 통해 이메일 동의 항목에 동의를 해야 우리가 원하는 이메일주소를 포함한 "email" 항목이 하나 더 온다.

Step 4. 나머지

from dj_rest_auth.registration.views import SocialLoginView
from allauth.socialaccount.providers.kakao import views as kakao_view
from allauth.socialaccount.providers.oauth2.client import OAuth2Client

class KakaoLogin(SocialLoginView):
    adapter_class = kakao_view.KakaoOAuth2Adapter
    callback_url = KAKAO_CALLBACK_URI
    client_class = OAuth2Client
# urls.py
urlpatterns = [
    path('kakao/login', kakao_login, name='kakao_login'),
    path('kakao/callback/', kakao_callback, name='kakao_callback'),
    path('kakao/login/finish/', KakaoLogin.as_view(), name='kakao_login_todjango'),
]

테스트

http://127.0.0.1:8000/api/user/kakao/login 접속

로그인하면 jwt 토큰들이 발급됨

유저도 잘 만들어짐

Authorization도 잘됨


Reference

[Django] Django REST framework(DRF) 환경에서 소셜 로그인(kakao) 구현하기 - 1)
[Django] Django REST framework(DRF) 환경에서 소셜 로그인(kakao) 구현하기 - 2)
kakao developers 카카오 로그인 공식문서

profile
일기장같은 공부기록📝

1개의 댓글

comment-user-thumbnail
2022년 11월 7일

if error is not None:
raise JSONDecodeError(error)
이 부분에서 JSONDecodeError, missing 2 required positional arguments 'doc' and 'pos' 라고 에러가 발생하는데 어떻게 해야할까요?

답글 달기