카카오 소셜로그인 구현

최성민·2023년 3월 30일
0

어플리케이션에 카카오 로그인을 도입하면 간편 회원가입을 할 수 있어서 사용자의 접근성을 높일 수 있다.
이를 위해선 카카오 디벨러퍼에서 카카오로그인 신청을 해야한다.
https://developers.kakao.com

카카오 로그인 신청

1. 카카오 developer 설정

  1. developers kakao > 내 애플리케이션 > 애플리케이션 추가하기

    결과화면

  2. 카카오 로그인 > 간편가입 > 비지니스 설정 바로가기 > 사업자 정보등록

    결과화면

    이런 식으로 했던거 같은데 정확하게는 기억이 안난다
    테스트?용으로 쓸수 있게해주는 탭이 있었던것 같다

    이렇게 해주면 다음과 같이 이메일을 필수 동의로 받을 수 있다.

  3. 사이트 도메인 등록, 리다이렉트 uri설정

  • 카카오 로그인이 성공했을때 이후에 리다이렉트될 프론트 페이지


    사이트 도메인 : 서버주소
    리다이렉트 URI : 프론트 카카오로그인 처리 페이지 주소

  1. 고급 설정 > 허용 IP주소


    이걸 안해주면 카카오에서 사용자정보를 받아오는 요청때 카카오에서 error json을 던져준다

2. 카카오 로그인 > code발급 > access_token > 사용자정보 받아오기

  1. 프론트에서 앱서버로 카카오 로그인 요청
# 프론트에서 http://127.0.0.1:8000/api/accounts/KakaoLogin/로 요청
# urls.py
path('KakaoLogin/', KakaoLogin, name='refresh_token'),

#views.py
def KakaoLogin(request):
	# 내 애플리케이션 > 앱 설정 > 요약 정보 > REST API KEY
    CLIENT_ID = settings.CLIENT_ID
    redirect_uri = "https://j8d103.p.ssafy.io/"
    return redirect(
        f"https://kauth.kakao.com/oauth/authorize?client_id={CLIENT_ID}&redirect_uri={redirect_uri}&response_type=code"
    )
  • 다음과 같이 요청시 장고에서 '카카오 REST API KEY'와 redirect uri을
  • https://kauth.kakao.com/oauth/authorize 주소에 파람으로 넣어주고
  • 로그인 페이지가 생성되며 KEY로 인증, redirect uri로 로그인 성공시 다음 화면 설정

결과화면

리다이렉트 uri
https://accounts.kakao.com/login/.../redirect_uri%3.../client_id%3...
response_type=code에 따라 카카오로그인 플로우가 달라진다

3. 프론트페이지에서 code파람추출

https://j8d103.p.ssafy.io/?code=6zfJMDvsyYDZ6gl2SfTN0S9jzjgLeZ4D51qtNTEMIherUx2svR2jHvNUGolpJs2JkdFpvAo9dJkAAAGHDESPgQ

  • 위의 마지막 캡쳐에서 파람으로 code값이 전송되는 것을 볼 수 있다
  • 이 code값은 프론트 카카오로그인 처리 페이지의 uri로 전송되야한다
  • 지금은 임시로 메인페이지에 넣었다
  • 프론트 처리페이지에서는 param으로 받은 code값을 axios로 앱서버로 보내준다

4. 앱서버 code > access_token > 사용자정보

  1. code로 access_token받아오기
import requests
def kakaoCallBack(request):
    code = request.GET.get("code")
    CLIENT_ID = settings.CLIENT_ID
    redirect_uri = "https://j8d103.p.ssafy.io/"

    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}"
    )
    token_json = token_request.json()
    error = token_json.get("error",None)


    if error is not None :
        return JsonResponse({"message": "INVALID_CODE"}, status = 400)
    access_token = token_json.get("access_token")
  1. access_token으로 사용자 정보(email)받아오기
	profile_json = profile_request.json()
    kakao_account = profile_json.get("kakao_account")
    email = kakao_account.get("email", None)
  1. 사용자정보로 회원가입 or 로그인 처리하기
	member = Member.objects.filter(email=email).first()
    ### 회원가입
    if member is None:
        nickname = kakao_account.get("profile", None).get("nickname")
        member = Member(email=email, nickname=nickname)
        member.set_password(settings.SOCIAL_LOGIN_PASSWORD)
        member.save()
        token = MyTokenObtainPairSerializer.get_token(member)
        refresh_token = str(token)
        access_token = str(token.access_token)
        response = JsonResponse({'email':member.email,'nickname':member.nickname,'access_token':access_token,'refresh_token':refresh_token}, status=200)
        return response
    ### 로그인
    else:
        token = MyTokenObtainPairSerializer.get_token(member)
        refresh_token = str(token)
        access_token = str(token.access_token)
        response = JsonResponse({'email':member.email,'nickname':member.nickname,'access_token':access_token,'refresh_token':refresh_token}, status=200)
        return response

5. 정리

  1. 카카오 디벨로퍼
  • 카카오싱크 신청
  • 허용 IP주소 설정
  • 사이트 도메인 설정
  • redirect uri설정
  1. 서버
  • redirect uri, api key로 카카오 로그인 요청
  • redirect url로 전달된 code를 받음
  • code로 access_token, 사용자정보 받아오기
  • 해당 사용자가 있으면 로그인, 없으면 회원가입처리
  1. 프론트
  • redirect uri로 받은 code값 서버로 전송
  • 대기페이지에서 로그인 성공시 메인페이지로 이동

6. 아쉬운점

  • redirect uri를 서버로 설정해서 한번에 다 처리했으면 더 깔끔했을 것 같다
  • 카카오 로그아웃을 구현하지 못해 프론트에 카카오세션?이 남아있는것

7. 최종코드

def kakao_login(request):
    """새로고침시 새로운 access_token 발송
    :param 
    :return str email, str nickname, str access_token, str refresh_token
    """
    client_id = settings.CLIENT_ID
    # redirect_uri = "http://localhost:3000/kakaologin/"
    redirect_uri = "https://j8d103.p.ssafy.io/kakaologin/"
    print("redirect_uri : ",redirect_uri)
    return redirect(
        f"https://kauth.kakao.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code"
    )
def kakao_callback(request):
    """새로고침시 새로운 access_token 발송
    :param str code
    :return 카카오로그인페이지
    """
    if request.method == 'POST':
        data = json.loads(request.body.decode('utf-8'))
        code = data.get("code")
        client_id = settings.CLIENT_ID
        redirect_uri = "https://j8d103.p.ssafy.io/kakaologin/"
        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}"
        )
        token_json = token_request.json()
        error = token_json.get("error",None)
        if error is not None :
            return JsonResponse({"message": "INVALID_CODE"}, status = 400)
        access_token = token_json.get("access_token")
        profile_request = requests.get(
            "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)
        member = Member.objects.filter(email=email).first()
        ### 회원가입
        if member is None:
            nickname = kakao_account.get("profile", None).get("nickname")
            member = Member(email=email, nickname=nickname)
            member.set_password(settings.SOCIAL_LOGIN_PASSWORD)
            member.save()
            token = MyTokenObtainPairSerializer.get_token(member)
            refresh_token = str(token)
            access_token = str(token.access_token)
            response = JsonResponse({'email':member.email,'nickname':member.nickname,'access_token':access_token,'refresh_token':refresh_token}, status=200)
            return response
        ### 로그인
        else:
            token = MyTokenObtainPairSerializer.get_token(member)
            refresh_token = str(token)
            access_token = str(token.access_token)
            response = JsonResponse({'email':member.email,'nickname':member.nickname,'access_token':access_token,'refresh_token':refresh_token}, status=200)
            return response
    return JsonResponse({'error': 'Only POST requests are allowed' },status=405)   
profile
칠전팔기 화이팅

0개의 댓글

관련 채용 정보