이번 포스팅에서는 장고 카카오 로그인을 구현해보려고 한다.
카카오 로그인은 카카오계정과 애플리케이션을 연결하고 토큰을 발급받아 카카오 API를 사용할 수 있도록 하는 기능이다.
카카오 로그인은 Kakao SDK for Android, iOS, JavaScript와 REST API로 제공되며 OAuth 2.0 기반이다.
아래 링크에 접속
내 어플리케이션 > 어플리케이션 추가하기
위의 폼을 입력하면 어플리케이션이 추가된 것을 확인할 수 있다.
아래와 같이 앱 키를 확인할 수 있는데 REST API 키를 복사해준다.
나는 환경변수 파일에 KAKAO_ID라는 이름으로 지정해주었다.
내 어플리케이션 > 제품설정 > 카카오 로그인에서 카카오 로그인 API를 활성화해야 서비스를 사용할 수 있다.
또, 아래와 같이 Redirect URI를 설정해준다.
※ 동의항목에서 여러 항목중 필요한 항목들도 설정
설정 완료 하고 나서, users/views.py에 아래와 같이 kakao_login함수를 정의한다.
카카오 로그인 request를 보내면, redirect 되어서 아래 주소로 가게 된다.
client_id는 환경변수 파일에서 설정해 준 REST API 키이고, REDIRECT_URI는 위와 같이 설정해준다.
※ urls.py에 경로 추가해줘야 함
def kakao_login(request):
client_id = os.environ.get("KAKAO_ID")
REDIRECT_URI = "http://127.0.0.1:8000/users/login/kakao/callback"
return redirect(
f"https://kauth.kakao.com/oauth/authorize?client_id={client_id}&redirect_uri={REDIRECT_URI}&response_type=code"
)
def kakao_callback(request):
try:
#(1)
code = request.GET.get("code")
client_id = os.environ.get("KAKAO_ID")
REDIRECT_URI = "http://127.0.0.1:8000/users/login/kakao/callback"
#(2)
token_request = requests.get(
f"https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id={client_id}&redirect_uri={REDIRECT_URI}&code={code}"
)
#(3)
token_json = token_request.json()
error = token_json.get("error", None)
if error is not None:
raise KakaoException()
#(4)
access_token = token_json.get("access_token")
#(5)
profile_request = requests.get(
"https://kapi.kakao.com/v2/user/me",
headers={"Authorization": f"Bearer {access_token}"},
)
profile_json = profile_request.json()
#(6)
email = profile_json.get("kakao_account", None).get("email")
if email is None:
raise KakaoException()
properties = profile_json.get("properties")
nickname = properties.get("nickname")
profile_image = properties.get("profile_image")
#(7)
try:
user = models.User.objects.get(email=email)
if user.login_method != models.User.LOGIN_KAKAO:
raise KakaoException()
except models.User.DoesNotExist:
user = models.User.objects.create(
email=email,
username=email,
first_name=nickname,
login_method=models.User.LOGIN_KAKAO,
email_verified=True,
)
user.set_unusable_password()
user.save()
#(8)
if profile_image is not None:
photo_request = requests.get(profile_image)
user.avatar.save(
f"{nickname}-avatar", ContentFile(photo_request.content)
)
login(request, user)
return redirect(reverse("core:home"))
except KakaoException:
return redirect(reverse("users:login"))
(1) kakao_login에서 request를 보내면, url의 code 값을 알아낼 수 있다.
(2) code를 얻었다면, kauth.kakao.com/oauth/token으로 POST를 한다.
(3) JSON을 얻는다.
(4) access_token을 얻는다.
(5) kapi.kakao.com/v2/user/me 으로 access_token을 보내고 profile_json을 받아온다.
※ profile_request.json() 에는 아래와 같은 속성을 갖고 있다.
(6) profile_request.json()으로 부터 email, nickname, profile_image등을 받아온다.
(7) 모델에 추가
(8) 프로필 이미지를 받아오는데, 이미지 URL이 나오지 않고 avatar파일로 저장하기 위함이다.
※ profile image URL이 나오는 것보다 더 좋은 방법이다. 만약 kakao 파일 구조가 변경되거나, 파일 이름이 바뀌면 avatar가 깨질 위험이 있다. 또 kakao로 로그인을 했지만 avatar를 바꾸고 싶을 수도 있기 때문에 (8)과 같은 방식이 더 좋은 방법이다.
참고 문헌
위 링크에 들어가보면 더 많은 정보를 얻을 수 있다.
'Web developer > Django' 카테고리의 다른 글
[Django] 함수 기반 뷰 vs. 클래스 기반 뷰 #DetailView (0) | 2020.11.14 |
---|---|
[Django] 함수 기반 뷰 vs. 클래스 기반 뷰 #ListView (0) | 2020.11.14 |
[Django] 장고 템플릿 #2 (0) | 2020.11.13 |
[Django] 장고 템플릿 #1 (0) | 2020.11.13 |
[Django] 쿼리셋(Query sets) (0) | 2020.11.09 |
댓글