관리 메뉴

공부 기록장 💻

카카오 소셜 로그인 과정 이해하기 본문

# Develop/Project

카카오 소셜 로그인 과정 이해하기

dream_for 2022. 9. 27. 13:37

오세유 프로젝트를 진행하면서, 기존에 개발했던 jwt 기반 auth 방식에서,
REST API를 통해 카카오 소셜 로그인으로 변경하는 것으로 결정하였다.
따라서 공식 문서 (https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#before-you-begin-process , https://developers.kakao.com/docs/latest/ko/kakaologin/common#authorization-consent-item ) 의 내용을 참고하여
먼저 카카오 로그인의 과정을 정리하며 이해를 돕고,NestJS 프레임워크 상에서 구현을 해보고자 한다.

카카오 로그인 기능

카카오 로그인은 카카오 계정으로 다양한 서비스에 로그인할 수 있도록 하는 소셜 로그인 서비스이다.
카카오 싱크는, 서비스 간편 가입 등 카카오 로그인에 더 다양한 확장 기능을 제공하는 비즈니스 솔루션이다.
카카오 로그인과 카카오 싱크에서 제공하는 기능들은 다음과 같다.


카카오 로그인이란?
카카오 로그인은 OAuth 2.0 기반 소셜 로그인 서비스로, 카카오톡 또는 카카오 계정으로 손쉽게 서비스에 로그인할 수 있다. 서비스 ID 및 비밀번호를 입력받고 검증하는 과정을 직접 구현하지 않고도 사용자에 대한 인증과 인가를 간편하고 안전하게 처리할 수 있다.

인증과 인가의 차이점
인증의 경우, ID와 비밀번호를 이용해 사용자의 신원을 확인하는 것이다. 즉, 카카오에 가입되어 있는 계정이 맞는지 확인하는 과정이다.
인가는, 사용자의 개인정보와 같은 자원(마이페이지나 친구 목록 조회, 채팅방 등)에 대한 권한을 획득하는 과정이다.
사용자에게 고유 토큰을 부여하여, 자원 접근 시 사용하게 된다.

인증(Authentication) ID와 비밀번호로 사용자 신원을 확인
각 서비스에 사용자가 카카오계정으로 로그인할 수 있는 기능 지원
서비스에서 각 사용자를 식별할 수 있는 고유한 회원번호 제공
인가(Authorization) 사용자 개인정보와 같은 자원(Resource)에 대한 접근 권한 획득
사용자 동의를 바탕으로 사용자 정보나 기능에 대한 접근 권한을 토큰 형태로 서비스에 부여


토큰의 종류
토큰은 사용자의 카카오 로그인 인증 및 인가 정보를 담은 권한 증명으로, 카카오 API 호출에 사용된다.
카카오 로그인은 OAuth 2.0 표준 규격에 따라 Access Toekn, Refresh Token 두 종류의 토큰을 발급한다.
Access Token은 사용자 인증과, 카카오 API 호출 권한을 위해 부여되며,
Refresh Token의 경우 액세스 토큰을 재발급할 때 부여되는 토큰이다. 만료 기간은 두달이며, 유효한 리프레시 토큰이 있는 경우 로그인 절차는 생략된다.

구분 설명 만료 시간
리프레시 토큰
(Refresh token)
액세스 토큰 재발급에 사용
유효한 리프레시 토큰이 있다면 사용자가 매번 카카오계정 정보를 입력하거나 카카오톡으로 로그인하는 인증 절차를 거치지 않아도 액세스 토큰 재발급 가능
2달
만료 시간 1달 남은 시점부터 갱신 가능
ID 토큰
(ID token)
카카오 로그인 사용자의 인증 정보를 제공하는 토큰
자세한 정보는 OpenID Connect 참고
액세스 토큰과 동일



카카오 싱크란 무엇인가?
카카오 싱크란, 카카오 로그인에 서비스 약관 동의와 카카오톡 채널 추가 기능을 더하여,
사용자가 한 번의 동의 과정만으로도 서비스의 신규 회원으로 가입할 수 있는 간편가입을 지원한다.
이를 도입하면, 서비스의 로그인 및 가입 절차를 대폭 간소화할 수 있으며 더 쉽게 회원을 확보 가능하다.
(로그인하여 얻은 토큰 값을 따로 갱신하거나, 카카오 계정에 따라 아이디를 저장하고 가입절차를 위한 개발 과정이 생략된다는 것이다.)



카카오 로그인 과정의 시퀀스 다이어그램



step 1. 카카오 로그인
1. 사용자가 서비스에서 카카오 로그인 버튼을 클릭. 서비스는 카카오 인증 서버로 인가 코드 발급을 요청
2. 카카오 인증 서버는 사용자에게 인증을 요청
- 카카오톡으로 로그인 : 카카오톡 실행, 카카오톡에 연결된 카카오 계정의 자격 정보로 사용자 인증
- 카카오계정으로 로그인: 계정 정보를 입력해 로그인하는 화면 출력, 해당 카카오계정의 자격정보로 사용자 인증

3. 카카오 인증 서버는 사용자 인증 성공 시, 서비스 앱의 동의항목 설정을 바탕으로 사용자에게 동의화면을 출력함
4. 사용자가 필수동의항목에 동의하고 로그인을 요청하면, 카카오는 인증 서버가 인가 코드(Authorization Code)를 발급해 서비스 앱에 등록된 Redirect URI로 전달
5. 서비스는 전달받은 인가 코드로 토큰을 요청하여 받음

step 2. 회원 확인 및 가입
1. 서비스는 카카오 로그인을 완료해 발급받은 토큰으로 사용자 정보 가져오기를 요청
2. 카카오 API 서버는 요청 시 사용된 토큰의 유효성을 검증하고, 요청을 처리하여 서비스에 응답
3. 서비스 서버는 카카오로부터 제공 받은 사용자 정보로 해당 사용자가 서비스에 회원 가입 되어 있는지 확인함
- 이미 가입된 사용자의 경우 STEP 3으로 넘어가기
- 회원 가입되어 있지 않은 사용자의 경우, 카카오에서 제공받은 사용자 정보(ID, email 등)으로 DB에 회원가입 처리

step 3. 서비스 로그인
1. 서비스 서버는 클라리언트에 해당 사용자의 로그인에 대한 세션을 발급함
2. 클라이언트는 서비스 세션을 전달받아 로그인 완료 처리하고, 사용자를 로그인된 서비스 화면으로 이동시킴



카카오 로그인 과정 시퀀스 다이어그램


다음은 REST API를 사용한 카카오 로그인 과정을 나타낸 시퀀스 다이어그램이다.
시퀀스 다이어그램에서 주체는 Service Client, Service Server, Kakao Auth Server로 나눌 수 있다.

Service Client는 화면을 통해 카카오 계정 로그인 요청을 보내는 역할을 한다.
오세유 백엔드 서버에서 개발하게 될 Service Server 부분에서는 Client로부터 받은 요청을 Kakao Auth Server로 보내는 중간다리 역할을 하게 된다. 로그인 과정에서 백엔드 서버는 Kakao Server에 토큰을 요청하고, 발급받은 토큰으로 유효성을 검증하며 회원 정보 확인 및 가입 처리를 하는 역할을 한다.

카카오 로그인 과정은 인가 코드 받기, 토큰 받기, 사용자 로그인 처리의 3가지 Step 으로 이루어진다.




Step 1. 인가 코드 받기

  1. 서비스 서버가 카카오 인증 서버로 인가 코드 받기를 요청한다.
  2. 카카오 인증 서버가 사용자에게 카카오 계정 로그인을 통한 인증을 요청한다.
    • 클라이언트에 유효한 카카오계정 세션이 있는 경우 4번으로 넘어감
  3. 사용자가 카카오 계정으로 로그인한다.
  4. 카카오 인증 서버가 사용자에게 동의 화면을 출력하여 인가를 위한 사용자 동의를 요청한다.
  5. 사용자가 필수 동의 항목에 동의하고 [동의하고 계속하기] 버튼 또는 [취소] 버튼을 누른다.
  6. 카카오 인증 서버는 서비스 서버의 Redirect URI로 인가 코드를 전달한다.
GET /oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code HTTP/1.1
Host: kauth.kakao.com



Step 2. 토큰 받기

  1. 서비스 서버가 Redirect URI로 전달 받은 인가 코드로 토큰 받기를 요청한다.
  2. 카카오 인증 서버가 토큰을 발급해 서비스 서버에 전달한다.


Step 3. 사용자 로그인 처리 (Service Server)

  1. 서비스 서버가 발급받은 Access Token으로 사용자 정보 가져오기를 요청하여, 사용자의 회원정보 및 정보를 조회하여 서비스의 회원인지 확인한다.
  2. 서비스 회원 정보 확인 결과에 따라 서비스 로그인 또는 회원 가입 과정을 진행한다.



Step 1. 인가 코드 받기

  1. 서비스 서버가 카카오 인증 서버로 인가 코드 받기를 요청한다.
  2. 카카오 인증 서버가 사용자에게 카카오 계정 로그인을 통한 인증을 요청한다.
    • 클라이언트에 유효한 카카오계정 세션이 있는 경우 4번으로 넘어감
  3. 사용자가 카카오 계정으로 로그인한다.
  4. 카카오 인증 서버가 사용자에게 동의 화면을 출력하여 인가를 위한 사용자 동의를 요청한다.
  5. 사용자가 필수 동의 항목에 동의하고 [동의하고 계속하기] 버튼 또는 [취소] 버튼을 누른다.
  6. 카카오 인증 서버는 서비스 서버의 Redirect URI로 인가 코드를 전달한다.
GET /oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code HTTP/1.1
Host: kauth.kakao.com




카카오 로그인 동의 화면을 호출하고, 사용자 동의를 거쳐 위의 HTTP 요청을 통해 인자 코드를 발급받게 된다.
동의 화면은 앱에 설정된 동의 항목에 대해 사용자에게 인가(동의)를 구한다. 인가 코드는 동의 화면을 통해 인가받은 동의 항목 정보를 갖고 있으며, 인가 코드를 사용해 토큰 받기 를 요청하게 된다.


이 때 동의 화면은 사용자와 앱이 처음 연결될 때만 나타난다. 이미 사용자가 이전에 동의를 완료한 경우, 해당 사용자의 카카오 로그인 시에는 동의 화면이 나타나지 않고 즉시 인가 코드가 발급 된다.
인가 코드 받기 요청은, 카카오 계정 세션이 없는 경우 사용자가 카카오 계정 정보를 입력하거나 카카오톡으로 로그인하는 인증 과정을 거쳐 동의 화면을 출력하게 되고, 카카오계정 세션이 존재하는 경우 카카오 계정 로그인 과정을 거치지 않고 바로 동의 화면을 출력한다.

사용자는 동의 화면에서 서비스 이용에 필요한 동의 항목에 동의하고, 로그인하거나 로그인을 취소할 수 있다.
카카오 인증 서버는 사용자의 선택에 따라 요청 처리 결과를 담은 Query String을 redirect_uri로 HTTP 302 Redirect 하게 된다. (이때 Redirect URI는 미리 등록된 값 중 하나여야 한다.)

- 사용자가 모든 필수 동의 항목에 동의한 경우 -> redirect_uri인가 코드를 담은 Query String 전달
- 사용자가 동의 화면에서 취소 버튼을 눌러 로그인 취소한 경우 -> redirect_uri에러 정보를 담은 Query String 전달


서비스 서버는 redirect_uri로 HTTP 302 리다이렉트된 요청의 Location에서 인가 코드 또는 에러를 확인해 다음과 같이 처리해야 한다.
1. 인가 코드 받기 요청 성공
- code 및 state 가 전달된 경우, code의 인가 코드 값으로 토큰 받기 요청
2. 인가 코드 받기 요청 실패
- error , error_description이 전달된 경우, 문제 해결, 응답 코드를 참고해 에러 원인별 상황에 맞는 서비스 페이지나 안내 문구를 사용자에게 보여주도록 처리


Request와 Response의 Parameter 값들은 다음과 같다.

Request

https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}


Parameter

Name Type Description Required
client_id String 앱 REST API 키
[내 애플리케이션] > [앱 키]에서 확인 가능
O
redirect_uri String 인가 코드를 전달받을 서비스 서버의 URI
[내 애플리케이션] > [카카오 로그인] > [Redirect URI]에서 등록
O
response_type String code로 고정 O
scope String 추가 항목 동의 받기 요청 시 사용
사용자에게 동의 요청할 동의 항목 ID 목록
동의 항목의 ID는 사용자 정보 또는 [내 애플리케이션] > [카카오 로그인] > [동의 항목]에서 확인 가능
쉼표(,)로 구분해 여러 개 전달 가능

주의: OpenID Connect를 사용하는 앱의 경우, scope 파라미터 값에 openid를 반드시 포함해야 함, 미포함 시 ID 토큰이 재발급되지 않음 (참고: scope 파라미터)
X
prompt String 카카오톡에서 자동 로그인, 기존 로그인 여부와 상관없이 로그인 요청 시 사용
동의 화면 요청 시 추가 상호작용을 요청하고자 할 때 전달하는 파라미터
쉼표(,)로 구분된 문자열 값 목록으로 전달

다음 값 사용 가능:
login: 기존 사용자 인증 여부와 상관없이 사용자에게 카카오계정 로그인 화면을 출력하여 다시 사용자 인증을 수행하고자 할 때 사용, 카카오톡 인앱 브라우저에서는 이 기능이 제공되지 않음
none: 사용자에게 동의 화면과 같은 대화형 UI를 노출하지 않고 인가 코드 발급을 요청할 때 사용, 인가 코드 발급을 위해 사용자의 동작이 필요한 경우 에러 응답 전달
X
service_terms String 약관 선택해 동의 받기 요청 시 사용
동의받을 약관 태그 목록
약관 태그는 [내 애플리케이션] > [간편가입]에서 확인 가능
쉼표(,)로 구분된 문자열 값 목록으로 전달
X
state String 카카오 로그인 과정 중 동일한 값을 유지하는 임의의 문자열(정해진 형식 없음)
Cross-Site Request Forgery(CSRF) 공격으로부터 카카오 로그인 요청을 보호하기 위해 사용
각 사용자의 로그인 요청에 대한 state 값은 고유해야 함
인가 코드 요청, 인가 코드 응답, 토큰 발급 요청의 state 값 일치 여부로 요청 및 응답 유효성 확인 가능
X
nonce String OpenID Connect를 통해 ID 토큰을 함께 발급받을 경우, ID 토큰 재생 공격을 방지하기 위해 사용
ID 토큰 유효성 검증 시 대조할 임의의 문자열(정해진 형식 없음)
X

* auth_type: Deprecated, prompt를 사용하도록 변경

Response


- 사용자가 [동의하고 계속하기] 를 선택하고 로그인을 진행하는 경우

HTTP/1.1 302 Found
Content-Length: 0
Location: ${REDIRECT_URI}?code=${AUTHORIZE_CODE}


- 로그인 취소를 한 경우

HTTP/1.1 302 Found
Content-Length: 0
Location: ${REDIRECT_URI}?error=access_denied&error_description=User%20denied%20access


Parameter

Name Type Description Requried
code String 토큰 받기 요청에 필요한 인가 코드 X
state String 요청 시 전달한 state 값과 동일한 값 X
error String 인증 실패 시 반환되는 에러 코드 X
error_description String 인증 실패 시 반환되는 에러 메시지 X




Step 2. 토큰 받기

다음으로, 인가 코드로 토큰발급을 요청한다. 필수 파라미터를 포함해 POST 요청을 보낸다.

POST /oauth/token HTTP/1.1
Host: kauth.kakao.com
Content-type: application/x-www-form-urlencoded;charset=utf-8


요청 성공 시, 응답은 토큰과 토큰 정보를 포함한다.
AccessToken을 이용해 사용자 정보 가져오기와 같은 카카오 API를 호출할 수 있다.
토큰 정보 보기로 액세스 토큰 유효성 검증 후, 사용자 정보 가져오기를 요청해 사용자 정보를 받아 서비스 회원 가입 및 로그인을 완료한다.

Request Parameter

Name Type Description Required
grant_type String authorization_code로 고정 O
client_id String 앱 REST API 키
[내 애플리케이션] > [앱 키]에서 확인 가능
O
redirect_uri String 인가 코드가 리다이렉트된 URI O
code String 인가 코드 받기 요청으로 얻은 인가 코드 O
client_secret String 토큰 발급 시, 보안을 강화하기 위해 추가 확인하는 코드
[내 애플리케이션] > [보안]에서 설정 가능
ON 상태인 경우 필수 설정해야 함
X

Response Parameter

Name Type Description Required
token_type String 토큰 타입, bearer로 고정 O
access_token String 사용자 액세스 토큰 값 O
id_token String ID 토큰
OpenID Connect 확장 기능을 통해 발급되는 ID 토큰, Base64 인코딩 된 사용자 인증 정보 포함

제공 조건: OpenID Connect가 활성화 된 앱의 토큰 발급 요청인 경우
또는 scope에 openid를 포함한 추가 항목 동의 받기 요청을 거친 토큰 발급 요청인 경우
X
expires_in Integer 액세스 토큰과 ID 토큰의 만료 시간(초)

참고: 액세스 토큰과 ID 토큰의 만료 시간은 동일
O
refresh_token String 사용자 리프레시 토큰 값 O
refresh_token_expires_in Integer 리프레시 토큰 만료 시간(초) O
scope String 인증된 사용자의 정보 조회 권한 범위
범위가 여러 개일 경우, 공백으로 구분

참고: OpenID Connect가 활성화된 앱의 토큰 발급 요청인 경우, ID 토큰이 함께 발급되며 scope 값에 openid 포함
X


ID 토큰 Payload

Name Type Description Required
iss String ID 토큰을 발급한 인증 기관 정보
https://kauth.kakao.com로 고정
O
aud String ID 토큰이 발급된 앱의 앱 키
인가 코드 받기 요청 시 client_id에 전달된 앱 키
Kakao SDK를 통한 카카오 로그인의 경우, 해당 SDK 초기화 시 사용된 앱 키
O
sub String ID 토큰에 해당하는 사용자의 회원번호 O
iat Integer ID 토큰 발급 또는 갱신 시각, UNIX 타임스탬프(Timestamp) O
exp Integer ID 토큰 만료 시간, UNIX 타임스탬프(Timestamp) O
auth_time Integer 사용자가 카카오 로그인을 통해 인증을 완료한 시각, UNIX 타임스탬프(Timestamp) O
nonce String 인가 코드 받기 요청 시 전달한 nonce 값과 동일한 값
ID 토큰 유효성 검증 시 사용
X
nickname String 닉네임
사용자 정보 가져오기의 kakao_account.profile.nickname에 해당

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진) 또는 닉네임
X
picture String 프로필 미리보기 이미지 URL
110px * 110px 또는 100px * 100px
사용자 정보 가져오기의 kakao_account.profile.thumbnail_image_url에 해당

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진) 또는 프로필 사진
X
email String 카카오계정 대표 이메일
사용자 정보 가져오기의 kakao_account.email에 해당

필요한 동의 항목: 카카오계정(이메일)
비고: ID 토큰 페이로드의 이메일은 유효하고 인증된 이메일 값이 있는 경우에만 제공, 이메일 사용 시 주의사항 참고
X

728x90
반응형
Comments