diff --git a/Baron SSO 로그인 방식 및 비표준 인증 흐름 정리.md b/Baron SSO 로그인 방식 및 비표준 인증 흐름 정리.md
index 35e5d5c..4c2b2fa 100644
--- a/Baron SSO 로그인 방식 및 비표준 인증 흐름 정리.md
+++ b/Baron SSO 로그인 방식 및 비표준 인증 흐름 정리.md
@@ -33,6 +33,50 @@ Baron SSO는 Ory Kratos와 Ory Hydra를 기반으로 한다.
참고로 `POST /api/v1/auth/sms`, `POST /api/v1/auth/verify-sms`도 존재하지만, 위의 "표준 2개 + 비표준 3개" 분류에서는 별도 보조 또는 내부 토큰 기반 흐름으로 보는 것이 적절하다.
+### 2.1 운영 요청 경로와 Gateway 역할
+
+운영 경로에서는 사용자의 요청이 곧바로 Backend, Kratos, Hydra로 들어가지 않는다. 앞단에는 Traefik 또는 외부 L7, Baron Gateway Nginx, Oathkeeper가 있다.
+
+현재 `gateway/nginx.conf` 기준 역할은 다음과 같다.
+
+| 경로 | Nginx 처리 | 다음 대상 |
+| --- | --- | --- |
+| `/api/*` | Backend API proxy | `baron_backend:3000` |
+| `/auth/*` | Ory Stack proxy | `oathkeeper:4455` -> Kratos public |
+| `/oidc/*` | Ory Stack proxy | `oathkeeper:4455` -> Hydra public |
+| `/` | UserFront 정적/앱 proxy | `baron_userfront:5000` |
+
+그림으로 보면 다음과 같다.
+
+```mermaid
+flowchart LR
+ User[사용자 브라우저]
+ RP[RP/업무시스템]
+ L7[Traefik 또는 외부 L7]
+ GW[Nginx Baron Gateway]
+ UF[UserFront]
+ BE[Baron Backend]
+ OK[Oathkeeper]
+ KR[Ory Kratos Public]
+ HY[Ory Hydra Public]
+
+ User --> RP
+ RP -->|OIDC /oidc/oauth2/auth| L7
+ User -->|Baron SSO 접속| L7
+ L7 --> GW
+ GW -->|/| UF
+ GW -->|/api/v1/*| BE
+ GW -->|/auth/*| OK
+ GW -->|/oidc/*| OK
+ OK -->|Kratos public API| KR
+ OK -->|Hydra public API| HY
+```
+
+따라서 로그인 흐름을 설명할 때는 다음 두 경로를 구분해야 한다.
+
+- 브라우저/API 호출 경로: `사용자 또는 RP -> L7 -> Nginx Gateway -> Backend/Oathkeeper`
+- 내부 백채널 경로: `Backend -> Kratos Admin/Public`, `Backend -> Hydra Admin`, `Kratos Courier -> Backend`
+
## 3. 표준 방식 2개
### 3.1 ID/Password
@@ -49,6 +93,31 @@ Kratos 인증이 성공하면 세션 토큰과 Kratos 세션 쿠키가 발급된
OIDC 로그인 중이면 `login_challenge`도 함께 전달된다. 이 경우 Backend는 Hydra의 login request를 확인한 뒤 `AcceptLoginRequest`를 호출하고, Hydra가 내려준 `redirectTo`를 UserFront에 반환한다. UserFront는 이 URL로 이동하여 RP의 OIDC 흐름을 계속 진행한다.
+그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant UF as UserFront
+ participant BE as Baron Backend
+ participant KR as Ory Kratos
+ participant HY as Ory Hydra
+ participant RP as RP/업무시스템
+
+ User->>RP: 업무시스템 접속
+ RP->>HY: OIDC 인증 요청
+ HY->>UF: login_challenge와 함께 로그인 화면 이동
+ User->>UF: ID/Password 입력
+ UF->>BE: POST /api/v1/auth/password/login
+ BE->>KR: password login flow 제출
+ KR-->>BE: Kratos session_token, session cookie
+ BE->>HY: AcceptLoginRequest(login_challenge, subject)
+ HY-->>BE: redirectTo 반환
+ BE-->>UF: redirectTo 반환
+ UF->>RP: OIDC callback으로 이동
+```
+
### 3.2 Login Code
Login Code는 Kratos의 `method=code` 기반 로그인이다. 사용자는 이메일 또는 전화번호 등으로 전달받은 코드를 입력하고, Backend는 Kratos login flow에 해당 코드를 제출한다.
@@ -61,6 +130,33 @@ Login Code는 Kratos의 `method=code` 기반 로그인이다. 사용자는 이
검증 성공 시 Kratos는 세션 토큰을 발급한다. Baron은 이 세션 토큰을 기준으로 UserFront 세션을 구성하거나, OIDC 흐름이 있으면 Hydra login accept로 이어간다.
+그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant UF as UserFront
+ participant BE as Baron Backend
+ participant KR as Ory Kratos
+ participant HY as Ory Hydra
+
+ User->>UF: 로그인 ID 입력
+ UF->>BE: 코드 로그인 시작 요청
+ BE->>KR: method=code login flow 시작
+ KR-->>User: 이메일/SMS 등으로 인증 코드 전달
+ User->>UF: 인증 코드 입력
+ UF->>BE: POST /api/v1/auth/login/code/verify
+ BE->>KR: VerifyLoginCode(loginId, flowID, code)
+ KR-->>BE: Kratos session_token
+ alt OIDC login_challenge 있음
+ BE->>HY: AcceptLoginRequest(login_challenge, subject)
+ HY-->>BE: redirectTo 반환
+ else 일반 UserFront 로그인
+ BE-->>UF: sessionJwt 반환
+ end
+```
+
## 4. 비표준 방식 3개
비표준 방식은 Kratos/Hydra의 표준 프로토콜만으로 끝나지 않고, Baron Backend가 `pendingRef`, Redis 상태, 폴링, 교차 기기 승인 같은 추가 상태 머신을 운영한다.
@@ -90,6 +186,33 @@ Enchanted Link는 사용자가 로그인 ID를 입력하면 Backend가 로그인
이 방식의 특징은 인증 요청 기기와 승인 기기가 분리될 수 있다는 점이다. 따라서 "누가 요청했는지"와 "누가 승인했는지"를 반드시 분리해서 기록해야 한다.
+그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant UF as 요청 브라우저
+ participant BE as Baron Backend
+ participant Redis as Redis
+ participant Approver as 링크/코드 승인 기기
+
+ User->>UF: 로그인 ID 입력
+ UF->>BE: POST /api/v1/auth/enchanted-link/init
+ BE->>Redis: pendingRef/status=pending 저장
+ BE-->>User: 로그인 링크 또는 코드 전달
+ loop 요청 브라우저 폴링
+ UF->>BE: POST /api/v1/auth/enchanted-link/poll
+ BE->>Redis: pendingRef 상태 조회
+ BE-->>UF: authorization_pending
+ end
+ User->>Approver: 링크 열기 또는 코드 검증
+ Approver->>BE: magic-link/code verify
+ BE->>Redis: pendingRef/status=approved, sessionJwt 저장
+ UF->>BE: poll 재시도
+ BE-->>UF: sessionJwt 반환
+```
+
### 4.2 Magic Link Verify
Magic Link Verify는 전달된 토큰을 검증하여 로그인 또는 승인만 수행하는 흐름이다.
@@ -113,6 +236,31 @@ Magic Link Verify는 전달된 토큰을 검증하여 로그인 또는 승인만
이 방식은 사용자가 링크를 누르는 위치에 따라 동작이 달라질 수 있다. 예를 들어 같은 브라우저에서 바로 로그인할 수도 있고, 다른 기기에서 원래 요청만 승인할 수도 있다.
+그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant BE as Baron Backend
+ participant Redis as Redis
+ participant UF as UserFront
+ participant Req as 원래 요청 브라우저
+
+ BE->>Redis: token -> loginId/pendingRef 저장
+ BE-->>User: Magic Link 전달
+ User->>UF: Magic Link 클릭
+ UF->>BE: POST /api/v1/auth/magic-link/verify
+ BE->>Redis: token 조회 및 만료 확인
+ alt verifyOnly=true
+ BE->>Redis: 원래 pendingRef 승인 처리
+ Req->>BE: poll
+ BE-->>Req: sessionJwt 또는 승인 결과 반환
+ else 현재 브라우저 로그인
+ BE-->>UF: token/sessionJwt 반환
+ end
+```
+
### 4.3 QR 로그인
QR 로그인은 요청 기기에서 QR을 표시하고, 이미 로그인된 승인 기기에서 QR을 스캔하여 요청 기기를 로그인시키는 흐름이다.
@@ -139,6 +287,32 @@ QR 로그인은 요청 기기에서 QR을 표시하고, 이미 로그인된 승
QR 로그인은 편의성이 높지만, 타인이 QR을 띄우고 사용자가 실수로 승인하는 상황을 반드시 방어해야 한다.
+그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Web as 요청 기기
+ participant BE as Baron Backend
+ participant Redis as Redis
+ participant Mobile as 승인 기기
+
+ Web->>BE: POST /api/v1/auth/qr/init
+ BE->>Redis: pendingRef/status=pending 저장
+ BE-->>Web: qrCode, pendingRef 반환
+ loop QR 상태 폴링
+ Web->>BE: POST /api/v1/auth/qr/poll
+ BE->>Redis: pendingRef 상태 조회
+ BE-->>Web: authorization_pending
+ end
+ Mobile->>Web: QR 스캔
+ Mobile->>BE: POST /api/v1/auth/qr/approve
+ BE->>BE: 승인 기기의 Kratos 세션 확인
+ BE->>Redis: pendingRef/status=approved, approverSubject 저장
+ Web->>BE: poll 재시도
+ BE-->>Web: sessionJwt 반환
+```
+
## 5. 비표준 방식의 공통 위험 지점
비표준 방식의 핵심 위험은 "요청 주체"와 "승인 주체"가 다를 수 있다는 데 있다.
@@ -390,6 +564,90 @@ Baron SSO의 로그인 방식은 표준 2개와 비표준 3개로 정리할 수
`#1247`, `#1248`, `#1241`에서 제안된 Headless 폰번호 로그인은 다음 흐름을 가진다.
+전체 흐름을 그림으로 보면 다음과 같다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant RP as RP/시스템
+ participant GW as Nginx Gateway
+ participant BE as Baron Backend
+ participant Redis as Redis
+ participant OK as Oathkeeper
+ participant KR as Ory Kratos
+ participant HY as Ory Hydra
+
+ User->>RP: 전화번호 입력 후 로그인 요청
+ RP->>GW: POST /api/v1/auth/headless/phone/login
+ Note over RP,GW: body 예시
client_id=headless-phone-client
phoneNumber=010-1234-5678
login_challenge=abc...
client_assertion=private_key_jwt
+ GW->>BE: /api 경로를 Backend로 proxy
+ BE->>BE: RP 서명 검증 및 전화번호 정규화
+ Note over BE: phoneNumber 정규화
010-1234-5678 -> +821012345678
+ BE->>Redis: phone pending/interception flag 저장
+ Note over BE,Redis: key 예시
prefixLoginCodePhonePending:+821012345678
TTL=5m
+ BE->>KR: InitiateLinkLogin(phoneNumber)
+ KR-->>BE: flowID 반환
+ BE->>Redis: phoneNumber -> flowID 저장
+ Note over BE,Redis: key 예시
prefixLoginCode:+821012345678 -> flowID
+ KR->>BE: Courier SMS 발송 웹훅 호출
+ Note over KR,BE: POST /api/v1/auth/webhooks/kratos-courier
recipient=+821012345678
template_data.login_code=123456
+ BE->>Redis: interception flag 확인
+ BE->>BE: Courier payload에서 login_code 추출
+ BE->>KR: VerifyLoginCode(phoneNumber, flowID, login_code)
+ KR-->>BE: Kratos session_token/session_id 발급
+ BE->>HY: AcceptLoginRequest(login_challenge, subject)
+ HY-->>BE: redirectTo 반환
+ BE-->>GW: redirectTo, sessionId, status 반환
+ GW-->>RP: JSON 응답 전달
+ RP->>GW: redirectTo 따라 /oidc/oauth2/auth 계속
+ GW->>OK: /oidc 경로를 Oathkeeper로 proxy
+ OK->>HY: strip /oidc 후 Hydra public으로 전달
+```
+
+이때 흐름 속 주요 데이터 예시는 다음과 같다.
+
+RP가 Backend로 보내는 요청:
+
+```json
+{
+ "client_id": "headless-phone-client",
+ "client_assertion": "eyJhbGciOiJSUzI1NiIs...",
+ "phoneNumber": "010-1234-5678",
+ "login_challenge": "b59a857064ef4827940bb..."
+}
+```
+
+Backend가 Redis에 저장하는 임시 키:
+
+```text
+prefixLoginCodePhonePending:+821012345678 = interception_flag
+prefixLoginCode:+821012345678 =
+TTL = 5m
+```
+
+Kratos Courier가 Backend로 보내는 발송 요청의 핵심 데이터:
+
+```json
+{
+ "recipient": "+821012345678",
+ "template_type": "login_code",
+ "template_data": {
+ "login_code": "123456"
+ }
+}
+```
+
+Backend가 RP로 반환하는 성공 응답:
+
+```json
+{
+ "status": "ok",
+ "redirectTo": "https://sso.example.com/oidc/oauth2/auth?login_verifier=...",
+ "sessionId": "a0f8dc4e-9400-4785-802c-..."
+}
+```
+
### 10.1 단계별 데이터 이동
#### Step 1. 인가 및 전화번호 식별