KR Kakao 인증 API 엔드포인트
목차
관련 문서
접근 권한 매트릭스
| 엔드포인트 | Public | 앱 토큰 | 사용자 JWT | 내부 운영자 | 비고 |
|---|---|---|---|---|---|
GET /auth/oauth/kakao | ✓ | ✓ | ✓ | ✓ | state/nonce 생성, CSRF 방지 헤더 필요 |
GET /auth/oauth/kakao/callback | ✓ | ✓ | ✓ | ✓ | Kakao redirect 전용, idempotency 필수 |
POST /auth/oauth/kakao/exchange | ✘ | ✓ | ✘ | ✘ | 앱 토큰 인증, 신규 사용자는 pending 상태 유지 |
POST /auth/oauth/kakao/provisioning/complete | ✘ | ✓ | ✘ | ✘ | appToken 기반 온보딩 제출 |
POST /auth/oauth/kakao/unlink | ✘ | ✘ | ✓ | ✓ | 사용자 JWT 필요, CSRF 헤더 검증 |
참고: Kakao 로그인 기능은
feature.auth.kakao플래그가 활성화된 환경에서만 노출됩니다.
카카오 OAuth 엔드포인트
📌 시퀀스 다이어그램: 카카오 로그인 전체 흐름
인가 URL 초기화 GET /auth/oauth/kakao
- 역할: Kakao OAuth 2.0 Authorization Code Grant를 시작할 인가 URL을 반환하고 state/nonce를 초기화합니다.
- 보안 포인트
- TimeMachine 기준 TTL 10분으로 Redis
auth:kr:kakao:session:*에 state/nonce를 저장합니다. - 이 단계를 생략하면 서버가 state/nonce를 제어할 수 없어 콜백 위·변조와 재전송 공격을 차단할 수 없습니다.
- 클라이언트는 반환된 state를 안전하게 보관하고 콜백에서 동일한 값을 전달해야 합니다.
- TimeMachine 기준 TTL 10분으로 Redis
- 응답 헤더:
Set-Cookie: kakao_auth_state=...; HttpOnly; Secure,Cache-Control: no-store
콜백 처리 GET /auth/oauth/kakao/callback
- 역할: Kakao authorization code를 수신해 state 검증, 토큰 교환, JWT 발급을 트리거합니다.
- 주요 작업
- Redis에서 state/nonce 및 idempotency 키(
auth:kr:kakao:idempotency:{state}) 확인 - Kakao 토큰 엔드포인트(
https://kauth.kakao.com/oauth/token) 호출로 access/refresh 토큰 수신 Auth Core의IssueSessionService호출로 JWT 액세스/리프레시 토큰 발급ExternalIdentityLink갱신 및KakaoAuthCompletedEvent발행
- Redis에서 state/nonce 및 idempotency 키(
- 응답: 기본적으로
302리다이렉트(app://auth/callback?...)로 JWT 전달, 필요 시 JSON 응답 대체 가능 - 보안 포인트: 웹 클라이언트는
POST /auth/oauth/kakao/exchange(AppTokenGuard 적용)를 통해 code를 교환하며, 신규 사용자의 온보딩 pending 상태를 appToken으로 추적한다.
프로비저닝 제출 POST /auth/oauth/kakao/provisioning/complete
- 역할: 신규 사용자 온보딩 폼을 접수하고, 프로비저닝 티켓을 단 한 번만 소비한다.
- 주요 작업
- AppTokenGuard로 인증된
appToken의 JTI를 기반으로 pending 세션을 조회하고 재사용을 차단한다. - 제출된 프로필 정보를 Redis
auth:kr:kakao:provision-submission:{appTokenId}에 보관 (TTL 24시간) - 운영 워크플로가 참고할 수 있도록 감사 로그, 이벤트 발행(향후 확장)
- AppTokenGuard로 인증된
- 응답:
202 Accepted+ 접수 메시지,400 KAKAO_PROVISIONING_SESSION_INVALID(세션 만료/중복)
연결 해제 POST /auth/oauth/kakao/unlink
- 역할: 기존 Kakao 외부 식별자를 내부 사용자 계정에서 분리하고 토큰을 폐기합니다.
- 요구 조건
- 사용자 JWT 액세스 토큰 필수, CSRF 헤더 검증
- unlink 사유(
USER_REQUEST,DATA_PORTABILITY등)를 요청 본문에 포함
- 결과:
ExternalAuthUnlinkedEvent발행, Kakao 리프레시 토큰 폐기 처리
요청/응답 계약
GET /auth/oauth/kakao
// Response 200
{
"authorizationUrl": "https://kauth.kakao.com/oauth/authorize?...",
"state": "f1556c2f-...",
"expireAt": "2025-01-20T10:32:00.000Z"
}
GET /auth/oauth/kakao/callback
| 파라미터 | 위치 | 필수 | 설명 |
|---|---|---|---|
code | query | 예 | Kakao authorization code |
state | query | 예 | Redis에 저장된 state 값 |
error, error_description | query | 아니오 | Kakao에서 전달하는 오류 케이스 |
- 성공 응답:
302 Redirect→Location: app://auth/callback?kakao=true&jwtAccessToken=... - 오류 응답:
400 Bad Request(state 불일치, code 만료),503 Service Unavailable(Kakao API 장애,Retry-After포함)
POST /auth/oauth/kakao/provisioning/complete
- 헤더:
Authorization: Bearer {appToken}
// Request
{
"name": "홍길동",
"organization": "SleepZ 운영팀",
"email": "operator@sleepz.dev"
}
// Response 202
{
"status": "accepted",
"message": "프로비저닝 요청이 접수되었습니다. 검토 후 이용 가능 여부를 안내드릴게요.",
"next": "/login?reason=session-required"
}
- 프로비저닝 세션이 만료되었거나 이미 사용된 경우
400 KAKAO_PROVISIONING_SESSION_INVALID를 반환합니다.
POST /auth/oauth/kakao/unlink
// Request
{
"reason": "USER_REQUEST"
}
// Response 200
{
"status": "unlinked",
"unlinkedAt": "2025-01-20T10:40:00.000Z"
}
- 사용자 JWT가 유효하지 않거나 CSRF 검증에 실패하면
401/403응답을 반환합니다.
오류 코드
| HTTP Status | 코드 | 설명 | 도메인 예외 |
|---|---|---|---|
| 400 | AUTH_KAKAO_STATE_MISMATCH | state 불일치 | KakaoStateMismatchError |
| 400 | AUTH_KAKAO_CODE_EXPIRED | authorization code 만료 | KakaoAuthorizationCodeExpiredError |
| 401 | AUTH_KAKAO_AUTHENTICATION_FAILED | Kakao 인증 실패 | KakaoAuthenticationFailedError |
| 409 | AUTH_KAKAO_ALREADY_LINKED | 다른 계정에 이미 연결됨 | KakaoIdentityAlreadyLinkedError |
| 503 | AUTH_KAKAO_PROVIDER_DOWN | Kakao API 장애 | KakaoProviderUnavailableError |
| 400 | KAKAO_PROVISIONING_SESSION_INVALID | 프로비저닝 세션 만료/중복 사용 | KakaoProvisioningStateInvalidError |
모니터링 및 로그 포맷
- 로그 태그:
event=kakao_auth,stage=request|callback|unlink,correlationId,state - 메트릭:
auth_kakao_login_latency_seconds,auth_kakao_callback_error_total - 모든 타임스탬프는 TimeMachine 기반 권한 있는 시각(
requestedAt,completedAt)으로 기록합니다.
변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 0.1.0 | 2025-10-20 | bok@weltcorp.com | 초기 엔드포인트 정의 |