# 인증/로그인 플로우 정리 (Backend IDP 추상화 기준) 이 문서는 **Backend IDP 추상화(IdentityProvider)**를 기준으로, 현재 지원하는 로그인 방식과 UserFront 연동 API, 그리고 **Kratos 세션 공유 방식**을 정리합니다. > 목적: ID/Password 방식부터 시작해, 현재 지원 중인 로그인 플로우를 **IDP 추상화를 해치지 않는 범위**에서 일관되게 구현하고, Front/Backend/Oathkeeper 간 세션 전달 방식을 명확히 한다. --- ## 1) 지원 로그인 방식 요약 | 방식 | Backend 엔드포인트 | 세션 토큰 반환 | 비고 | |---|---|---|---| | ID/Password | `POST /api/v1/auth/password/login` | `sessionJwt` | IDP 추상화 사용 (Ory/Descope) | | Enchanted Link (Email/SMS) | `POST /api/v1/auth/enchanted-link/init` → `POST /api/v1/auth/enchanted-link/poll` | `sessionJwt` | Ory는 `/api/v1/auth/login/code/verify`/`verify-short`(verifyOnly) 사용 | | Magic Link Verify | `POST /api/v1/auth/magic-link/verify` | `token` | 비-Ory 경로(verifyOnly 가능) | | SMS 코드 | `POST /api/v1/auth/sms` → `POST /api/v1/auth/verify-sms` | `token` | 현재는 내부 토큰(placeholder). Kratos 세션 교환 필요 | | QR 로그인 | `POST /api/v1/auth/qr/init` → `POST /api/v1/auth/qr/poll` | `sessionJwt` | 모바일 승인: `POST /api/v1/auth/qr/approve` | --- ## 2) UserFront 연동 API 매핑 ### 2.1 ID/Password 로그인 1. `POST /api/v1/auth/password/login` 2. 응답의 `sessionJwt` 사용 ### 2.2 Enchanted Link (Email/SMS) 1. `POST /api/v1/auth/enchanted-link/init` → `pendingRef` 수신 2. `POST /api/v1/auth/enchanted-link/poll`로 폴링 3. 사용자가 링크 클릭하면 UserFront가 아래 중 하나 호출 - Ory: `POST /api/v1/auth/login/code/verify` 또는 `/api/v1/auth/login/code/verify-short` (verifyOnly=1) - 비-Ory: `POST /api/v1/auth/magic-link/verify` (verifyOnly=1) 4. Polling 응답에서 `sessionJwt` 수신 (승인 후 Backend에서 세션 발급) ### 2.3 QR 로그인 1. `POST /api/v1/auth/qr/init` → `qrCode`, `pendingRef` 수신 2. 웹은 `POST /api/v1/auth/qr/poll`로 폴링 3. 모바일 앱은 `POST /api/v1/auth/qr/approve`로 승인 (모바일 세션 토큰은 승인 검증용) 4. Polling 응답에서 `sessionJwt` 수신 ### 2.4 SMS 코드 로그인 1. `POST /api/v1/auth/sms`로 코드 발송 2. `POST /api/v1/auth/verify-sms`로 코드 검증 3. 현재는 내부 토큰 반환 (IDP 세션 교환은 TODO) --- ## 3) Kratos 세션 생성/공유 방식 ### 3.1 생성 (ID/Password 기준) - Backend가 IDP 추상화(`IdentityProvider.SignIn`)를 호출해 `sessionJwt`를 발급 - **Ory(Kratos)**의 경우: - Kratos Login API를 통해 `session_token`을 반환 - 이 값이 `sessionJwt`로 응답됨 ### 3.2 공유 (Backend → UserFront / Oathkeeper) 현재 공유 방식은 **두 가지 선택지**가 있습니다. **A) Backend가 쿠키로 전달 (권장 방향)** - `sessionJwt`가 Kratos `session_token`인 경우 `ory_kratos_session` 쿠키로 `Set-Cookie` - Oathkeeper `cookie_session` authenticator가 Kratos `/sessions/whoami`로 검증 가능 **B) UserFront가 토큰을 보관/전달 (현재 동작)** - `sessionJwt`를 로컬에 저장 후 Backend 호출 시 `Authorization: Bearer `로 전달 - Oathkeeper 경유 경로에서는 쿠키가 필요하므로, 별도 토큰 교환 또는 Oathkeeper 인증기 추가가 필요 > 현재 구현은 **B 방식에 가깝고**, Oathkeeper 통과를 위한 쿠키 전달은 추가 구현이 필요합니다. --- ## 4) IDP 추상화 관점에서의 구현 상태 - **ID/Password 로그인**: IDP 추상화 사용 (Ory/Descope) — 정상 - **Enchanted/Magic Link**: 현재는 Descope 기반 로직이 포함됨. Ory 전환 시 Kratos `code/link` 플로우로 교체 필요 - **SMS 코드**: 내부 토큰(placeholder). Kratos 세션 교환 로직 추가 필요 - **QR 로그인**: 모바일 세션 토큰은 승인 검증용으로만 사용하고, 백엔드에서 웹 전용 세션을 새로 발급 --- ## 5) 링크 로그인 ↔ QR 로그인 공유/분리 로직 ### 5.1 공유되는 로직 (공통 기반) - **IDP 코드 검증 로직 공유**: Ory 기준으로 링크 로그인과 QR 로그인 모두 `VerifyLoginCode`(코드 기반 로그인 검증)를 사용합니다. - **Kratos courier relay 공유**: Kratos에서 발송되는 `login_code`를 `HandleKratosCourierRelay`에서 처리하며, 링크/QR 모두 이 경로를 거칩니다. - **코드/플로우 상태 저장**: 코드 로그인 플로우의 `flow_id`는 공통 키(`prefixLoginCode`)에 저장됩니다. ### 5.2 분리되는 로직 (pendingRef/승인 경로) - **pendingRef 네임스페이스 분리**: - 링크 로그인: `prefixSession`, `prefixLoginCodePending`, `prefixLoginMethod`, `prefixLoginFlow` - QR 로그인: `prefixLoginCodeQrPending`, `prefixLoginCodeQr`, `prefixQrPending`, `prefixQrMeta`, `prefixQrApproverSession` - **승인 엔드포인트 분리**: - 링크 로그인: `/api/v1/auth/magic-link/verify` 또는 `/api/v1/auth/login/code/verify*` (verify-only) - QR 로그인: `/api/v1/auth/qr/approve` - **세션 발급 주체 분리**: - 링크 로그인: Polling(요청 기기 A)에서 세션 발급 - QR 로그인: Polling(웹)에서 세션 발급, 모바일은 승인만 수행 - **audit 기록 경로 분리**: - 링크 로그인: `writeLinkAuditLog` - QR 로그인: `writeQrAuditLog` ### 5.3 verify-only 적용 범위 - 링크 로그인/코드 로그인 경로에만 적용됩니다. - QR 로그인은 approve/poll 구조이므로 verify-only를 사용하지 않습니다. --- ## 6) UserFront 주의사항 - `sessionJwt`가 **JWT 형식이 아닐 수 있음** (Kratos session token은 opaque 가능) - 현재 UserFront는 Descope SDK 기반 세션 처리 로직을 제거했으니 남아 있다면 제거 대상임. 즉시 사용자에게 알리고 이슈로 생성 바람. 참고. - AdminFront, DevFront는 JWT 방식으로 RP중 하나인 것 처럼 동작시키는 설계. 따라서 JWT에 대한 대응도 내부적으로는 완벽히 진행해야 함.