카카오 로그인 연동 가이드
개요
카카오 로그인은 모바일 앱(iOS, Android) 사용자가 Kakao OAuth 2.0 인가를 통해 우리 서비스에 인증하고,
백엔드가 JWT 액세스/리프레시 토큰을 발급하는 표준 흐름입니다. 이 문서는 모바일 클라이언트,
백엔드(dha-sleep-api), Kakao OAuth 서버 간 상호작용을 한눈에 파악할 수 있도록
시퀀스 다이어그램과 단계별 설명을 제공합니다.
상세 도메인 규칙은 KR Auth 도메인 문서를, 엔드포인트 계약은 KR Auth 엔드포인트를 참고하세요.
전체 로그인 흐름 요약
- 모바일 앱이 백엔드
/auth/oauth/kakao엔드포인트로 인가 URL을 요청합니다. - 백엔드는 state/nonce를 TimeMachine 기준 TTL(10분)로 Redis에 저장하고 인가 URL을 반환합니다.
- 모바일 앱은 Kakao SDK 또는 브라우저로 인가 URL을 열어 사용자의 Kakao 인증·동의를 진행합니다.
- Kakao 서버는 authorization code와 state를 백엔드 콜백
(
/auth/oauth/kakao/callback)으로 전달합니다. - 백엔드는 state 검증 및 Kakao 토큰 교환을 수행한 뒤
Auth Core에 JWT 발급을 위임합니다. - 백엔드는 앱 스킴으로 리다이렉트하면서 JWT 액세스/리프레시 토큰을 전달하거나, 앱 전용 API 응답으로 토큰을 반환합니다.
시퀀스 다이어그램
단계별 상세
1. 인가 URL 초기화 (모바일 → 백엔드)
- 엔드포인트:
GET /auth/oauth/kakao - 응답:
authorizationUrl,state,expireAt - 중요 포인트
- state/nonce는 TimeMachine 기준 TTL 10분으로 Redis
auth:kr:kakao:session:*에 저장합니다. - 이 단계가 없으면 클라이언트가 직접 Kakao로 이동하게 되어 state/nonce를 서버가 제어할 수 없으므로 콜백 위·변조, 재전송 공격을 방지하기 어렵습니다.
- 모바일은 반환된 state를 안전하게 보관 후 Kakao 콜백에서 그대로 전달해야 합니다.
- state/nonce는 TimeMachine 기준 TTL 10분으로 Redis
2. Kakao 인증 진행 (모바일 ↔ Kakao)
- 모바일은 Kakao SDK, 앱 스킴, 또는 WebView로 인가 URL을 열어 사용자의 Kakao 계정 인증과 동의를 받습니다.
- 인증 완료 후 Kakao는 사전에 등록된 리다이렉트 URI로 code/state를 전달하며, 모바일은 이를 백엔드에 위임합니다.
3. 콜백 처리 및 Kakao 토큰 교환 (모바일 → 백엔드 → Kakao)
- 엔드포인트:
GET /auth/oauth/kakao/callback - 백엔드는 다음을 수행합니다.
- state 값 검증 및 Redis idempotency 키(
auth:kr:kakao:idempotency:{state}) 확인 - Kakao 토큰 엔드포인트(
https://kauth.kakao.com/oauth/token)와 코드 교환 진행 - Kakao 사용자 ID, 프로필 동의 항목을 내부 모델(
KakaoUserId)로 변환
- state 값 검증 및 Redis idempotency 키(
4. 내부 사용자 연동 및 JWT 발급 (백엔드 ↔ Auth Core)
CompleteKakaoAuthService는Auth Core의IssueSessionService를 호출해 JWT 액세스/리프레시 토큰을 발급받습니다.- 신규 사용자라면
UserProvisionRequiredEvent를 발행하고, 기존 사용자라면ExternalIdentityLink를 갱신합니다. - 발급 결과는 Kakao 로그인 완료 이벤트(
KakaoAuthCompletedEvent)와 함께 다운스트림 도메인으로 전파됩니다.
5. 최종 응답 및 이동 (백엔드 → 모바일)
- 기본 시나리오:
302리다이렉트로 앱 스킴(app://auth/callback?kakao=true&jwtAccessToken=...)에 JWT 토큰을 전달합니다. - 대체 시나리오: 모바일이 폴링/딥링크를 사용할 수 없는 경우 JSON 응답으로 액세스/리프레시 토큰을 반환합니다.
- 모바일은 JWT를 안전한 저장소(Keychain, Keystore 등)에 저장하고 이후 API 호출 시
Authorization: Bearer헤더에 포함합니다.
요청/응답 체크리스트
| 단계 | 요청자 | 핵심 헤더/파라미터 | 성공 시 결과 |
|---|---|---|---|
| 인가 URL 요청 | Mobile → Backend | User-Agent, X-Platform, country=KR | state/nonce, authorizationUrl, expireAt |
| Kakao 인증 | Mobile ↔ Kakao | OAuth 표준 파라미터 (response_type=code, client_id) | Authorization Code, state |
| 콜백 처리 | Mobile → Backend | code, state, (선택) lang, appVersion | Kakao 토큰 교환, 외부 ID 링크 |
| JWT 발급 | Backend → AuthCore | kakaoUserId, provider='kakao' | JWT accessToken, refreshToken |
| 최종 리다이렉트 | Backend → Mobile | Location: app://...jwtAccessToken=... | 모바일이 JWT 저장 후 후속 호출 |
보안 및 운영 고려사항
- State/Nonce 검증: 모든 콜백에서 state가 일치하는지 확인하고, 만료 또는 불일치 시
도메인 예외(
KakaoStateMismatchError)를 반환합니다. - Idempotency: 동일한 콜백이 반복될 경우 Redis idempotency 키로 재처리를 차단합니다.
- TimeMachine 사용: 모든 만료 시각 계산과 감사 로그는 TimeMachine에서 제공하는 권한 있는 시각을 사용합니다.
- 토큰 저장소: 모바일은 JWT를 안전한 저장소(Keychain/Keystore)에 저장하고, 탈옥·루팅 탐지 및 무결성 검사를 권장합니다.
- 모니터링:
auth_kakao_login_latency_seconds,auth_kakao_login_failure_total지표를 수집하고 Alert 기준을 설정합니다. - Feature Flag: Kakao OAuth 장애 시
feature.auth.kakao를 비활성화하여 폴백 로그인 경로를 안내합니다.