OAuth 2.0 기반 Kakao 소셜 로그인 서비스는 Kakao Developers 공식 문서에 잘 정리가 되어 있습니다. 이 글은 공식 문서를 나름대로의 방식으로 정리한 것입니다.
애플리케이션 등록 과정은 생략
카카오 로그인은 다양한 서비스 개발 환경에서 손쉽게 사용할 수 있도록 REST API 뿐만 아니라 JavaScript, Android, iOS, Flutter 플랫폼용 Kakao SDK(SOftware Development Kit)를 제공한다.
로그인
로그인은 사용자가 자신을 인증해 서비스에 권한을 인가하는 절차이다. 로그인 완료 시 보안 데이터인 토큰을 서비스에 발급한다. 서비스는 토큰을 요청에 포함해 요청의 자격을 증명할 수 있다.
서비스 로그인 과정
사용자 클라이언트에서 사용자가 카카오 로그인 버튼을 선택하면, 서비스는 카카오 API 플랫폼 서버로 인가 코드 발급을 요청
카카오 API 플랫폼 서버는 사용자에게 인증을 요청하고, 성공 시 사용자에게 동의 화면으로 인가를 요청
인가 완료 후 카카오 API 플랫폼 서버는 인가 코드를 포함한 Redirect URI로 사용자를 리다이렉트
서비스가 Redirect URI에 포함된 인가 코드로 토큰 발급을 요청하면, 카카오 API 플랫폼은 사용자와 서비스 앱을 연결하고 서비스에 사용자의 토큰을 발급
회원 확인 및 등록
서비스 로그인
토큰은 사용자의 인증과 권한 정보를 담은 문자열이다. 서비스는 인가 결과로 발급받은 인가 코드로 토큰 발급을 요청할 수 있고, 발급받은 토큰을 API 요청에 포함해서 기능 사용 권한이 있음을 증명한다.
카카오 로그인은 OAuth 2.0 표준 규격에 따라 액세스 토큰(Access token), 리프레시 토큰(Refresh token) 두 종류의 토큰을 발급한다. OpenID Connect를 활성화하면 ID 토큰을 추가로 발급받을 수 있다.
Supabase에서는 OpenID Connect 방식을 활성화해서 ID 토큰을 사용한다.
토큰별 역할과 만료 시간
REST API를 사용한 카카오 로그인 과정을 나타낸 시퀀스 다이어그램
인가 코드 받기
https://kauth.kakao.com/oauth/authorize
[요청]
Quert Parameter: 일부만 정리
openid
를 반드시 포함[응답]
Query Parameter
토큰 받기
요청에 필요한 인가 코드요청 예제
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}
응답 예제
HTTP/1.1 302
Content-Length: 0
Location: ${REDIRECT_URI}?code=${AUTHORIZE_CODE}
서비스 서버는 기존에 설정한 redirect_uri
로 HTTP 302 리다이렉트된 요청의 Location에서 인가 코드 또는 에러를 확인해 처리해야 한다.
code
및 state
전달code
의 인가 코드 값으로 토큰 받기
요청error
, error_description
전달토큰 받기
https://kauth.kakao.com/oauth/token
[요청]
Header
Body
[응답]
Body
요청 예제
curl -v -X POST "https://kauth.kakao.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded;charset=utf-8" \
-d "grant_type=authorization_code" \
-d "client_id=${REST_API_KEY}" \
--data-urlencode "redirect_uri=${REDIRECT_URI}" \
-d "code=${AUTHORIZE_CODE}"
응답 예제: ID 토큰 포함
HTTP/1.1 200
{
"token_type": "bearer",
"access_token": "${ACCESS_TOKEN}",
"id_token": "${ID_TOKEN}",
"expires_in": 7199,
"refresh_token": "${REFRESH_TOKEN}",
"refresh_token_expires_in": 86399,
"scope": "profile_image openid profile_nickname"
}
ID 토큰 페이로드
{
"aud": "${APP_KEY}",
"sub": "${USER_ID}",
"auth_time": 1661967952,
"iss": "https://kauth.kakao.com",
"exp": 1661967972,
"iat": 1661967952,
"nickname": "JordyTest",
"picture": "http://yyy.kakao.com/.../img_110x110.jpg",
"email": "jordy@kakao.com"
}
토큰 정보 보기
https://kapi.kakao.com/v1/user/access_token_info
- code: -1, HTTP Status: 400
- 카카오 서비스의 일시적 내부 장애 상태, 토큰을 강제 만료 또는 로그아웃 처리하지 않고 일시적인 장애 메시지로 처리 권장
- code: -2, HTTP Status: 400
- 필수 인자가 포함되지 않은 경우나 호출 인자값의 데이터 타입이 적절하지 않거나 허용된 범위를 벗어난 경우
- code: -401, HTTP Status: 401
- 유효하지 않은 앱키나 액세스 토큰으로 요청한 경우, 토큰 값이 잘못되었거나 만료되어 유효하지 않은 경우로 토큰 갱신 필요
[요청]
Header
[응답]
Body
요청 예제
curl -v -G GET "https://kapi.kakao.com/v1/user/access_token_info" \
-H "Authorization: Bearer ${ACCESS_TOKEN}"
응답 예제
HTTP/1.1 200 OK
{
"id":123456789,
"expires_in": 7199,
"app_id":1234
}
토큰 갱신하기
https://kauth.kakao.com/oauth/token
토큰 받기
와 마찬가지로 JSON 객체로 전달, 응답 중 refresh_token
값은 요청 시 사용된 리프레시 토큰의 만료 시간이 1개월 미만으로 남았을 때만 갱신되어 전달된다.[요청]
Header
Body
[응답]
Body
요청 예제
curl -v -X POST "https://kauth.kakao.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded;charset=utf-8" \
-d "grant_type=refresh_token" \
-d "client_id=${REST_API_KEY}" \
-d "refresh_token=${USER_REFRESH_TOKEN}"
응답 예제
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
{
"access_token":"${ACCESS_TOKEN}",
"token_type":"bearer",
"refresh_token":"${REFRESH_TOKEN}", //optional
"refresh_token_expires_in":5184000, //optional
"expires_in":43199,
}
사용자 정보 가져오기
https://kapi.kakao.com/v2/user/me
[요청-액세스 토큰 방식]
Header
Authorization: Bearer ${ACCESS_TOKEN}
Query Parameter
[응답]
Body
KakaoAccount
Profile
요청 예제: 액세스 토큰 방식으로 email 정보 받기
curl -v -X POST "https://kapi.kakao.com/v2/user/me" \
-H "Content-Type: application/x-www-form-urlencoded;charset=utf-8" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-urlencode 'property_keys=["kakao_account.email"]'
응답 예제: 닉네임만 받는 경우
HTTP/1.1 200 OK
{
"id":123456789,
"connected_at": "2022-04-11T01:45:28Z",
"kakao_account": {
"profile_nickname_needs_agreement": false,
"profile": {
"nickname": "홍길동"
}
},
"properties":{
"${CUSTOM_PROPERTY_KEY}": "${CUSTOM_PROPERTY_VALUE}",
...
}
}
카카오 로그인은 OAuth 2.0 기반의 표준 인증 프로토콜인 OpenID Connect(OIDC)를 지원한다. OIDC를 서비스에 적용하면 사용자의 로그인을 더 안전하게 처리할 수 있다.
https://kauth.kakao.com/.well-known/openid-configuration
[응답]
Body
https://kauth.kakao.com
으로 고정... 등등 (자세한 응답값은 문서 확인)
요청 예제
curl -v -G GET "https://kauth.kakao.com/.well-known/openid-configuration"
응답 예제
HTTP/1.1 200
Content-Type: application/json;charset=utf-8
{
"issuer": "https://kauth.kakao.com",
"authorization_endpoint": "https://kauth.kakao.com/oauth/authorize",
"token_endpoint": "https://kauth.kakao.com/oauth/token",
"userinfo_endpoint": "https://kapi.kakao.com/v1/oidc/userinfo",
"jwks_uri": "https://kauth.kakao.com/.well-known/jwks.json",
"token_endpoint_auth_methods_supported": ["client_secret_post"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"],
"request_uri_parameter_supported": false,
"response_types_supported": ["code"],
"response_modes_supported": ["query"],
"grant_types_supported": [
"authorization_code", "refresh_token"
],
"code_challenge_methods_supported": ["S256"],
"claims_supported": [
"iss",
"aud",
"sub",
"auth_time",
"exp",
"iat",
"nonce",
"nickname",
"picture",
"email"
]
}
카카오 로그인 구현하기
Open ID Connect를 활성화 후, 카카오 로그인을 구현한다.
OIDC를 활성화한 앱은 사용자 인증 정보가 담긴 ID 토큰을 액세스 토큰과 함께 발급하고, OIDC: 사용자 정보 가져오기로 표준 규격을 준수한 형태의 사용자 정보를 제공받을 수 있다.
ID 토큰 유효성 검증하기
발급받은 ID 토큰은 서비스 보안을 위해 유효성을 검증하고 사용해야 한다. 페이로드 값 확인 시, 필요에 따라 디버깅 목적으로 제고아는 ID 토큰 정보 보기 API를 사용할 수 있다. 아래 순서로 ID 토큰을 검증한다.
iss
: https://kauth.kakao.com
와 일치해야 함aud
: 서비스 앱 키와 일치해야 함exp
: 현재 UNIX 타임스탬프보다 큰 값 필요nonce
: 카카오 로그인 요청 시 전달한 값과 일치해야 함kid
에 해당하는 공개키 값 확인RFC7515
규격에 따라 서명 검증 가능ID 토큰은 서비스의 로그인 세션 대신 사용할 수 있는 JWT 형식의 토큰이다. 서비스는 ID 토큰에 포함된 사용자 인증 정보를 서비스에 활용하거나, ID 토큰의 유효성을 검증할 수 있다. ID 토큰의 만료 시간은 액세스 토큰과 동일하다.
ID 토큰의 세 가지 영역
Header: ID 토큰의 규격 정보, 카카오 로그인으로 발급받는 ID 토큰의 헤더는 alg, typ, kid 3가지 정보를 포함함
Payload: 사용자 인증 정보
https://kauth.kakao.com
으로 고정Signature: 카카오 인증 서버에서 kid에 해당하는 공개키로 서명한 값, RS256 방식으로 암호화된 값으로, ID 토큰 유효성 검증 시 서명
ID 토큰은 세 영역의 값을 Base64 인코딩 한 후 온점(.)으로 이어 붙인 하나의 문자열로 생성된다. 따라서 온점을 기준으로 각 영역을 분리하고, Base64 디코딩하여 내용을 확인할 수 있다. 페이로드와 서명의 검증 방법은 이전에 소개한 ID 토큰 유효성 검증하기
를 따르면 된다.
출처
https://developers.kakao.com/docs/latest/ko/kakaologin/common