{ "version": "1.1", "id": "ap4-edge-forward-auth-flow", "title": "AP4 proxy session에서 trusted identity JSON까지", "question": "AP4에서 AP4_SESSION은 어떤 순서로 검증되고 allowlisted identity header와 internal token을 거쳐 JSON이 되는가?", "type": "sequence", "direction": "LR", "audience": [ "forward-auth와 upstream header trust를 검토하는 플랫폼 개발자" ], "summary": "Nginx가 oauth2-proxy에 internal auth subrequest를 보내 session을 확인하고, 인증 결과로 client identity header를 덮어쓴 뒤 internal token과 함께 Spring upstream을 호출한다.", "alt": "브라우저, Nginx, oauth2-proxy, Spring upstream 사이에서 AP4_SESSION 검증, identity header 덮어쓰기, internal token 검증과 JSON 응답이 이어지는 순서도.", "long_description": "브라우저가 AP4_SESSION cookie로 Nginx의 /api/edge를 호출한다. Nginx는 oauth2-proxy의 internal auth endpoint에 subrequest를 보내고 인증된 user와 email 결과를 받는다. 이어서 client가 보낸 동명 header를 사용하지 않고 oauth2-proxy 결과와 Nginx 환경의 internal token으로 /edge/me 요청을 새로 조립한다. Spring controller가 user header와 internal token을 함께 확인해 identity JSON을 만들고 Nginx가 브라우저에 전달한다.", "source_context": { "document": "document.md", "document_sha256": "df4d1a604c74e756672b5b40510abfedb8c67b39af280a5f51985ea9972f5371", "anchor": { "kind": "marker", "value": "ap4-edge-forward-auth-flow", "line": 1108 } }, "composition": { "profile": "sequence", "diagram_only": true, "reference_ids": [ "payment-approval-sequence" ], "rationale": "외부 요청, auth subrequest, auth 결과, upstream rewrite와 JSON 응답이 엄격한 순서로 이어지므로 sequence 문법이 신뢰 경계의 변환 시점을 가장 잘 보여 준다.", "focus_node": "nginx" }, "groups": [], "nodes": [ { "id": "browser", "label": "브라우저", "kind": "participant", "role": "participant", "description": "AP4_SESSION cookie와 함께 edge endpoint를 호출하는 외부 client.", "evidence": [ { "start_line": 992, "end_line": 1007 } ], "assumption": false }, { "id": "nginx", "label": "Nginx edge", "kind": "participant", "role": "participant", "emphasis": "primary", "description": "Internal auth subrequest를 만들고 인증 결과를 allowlisted upstream header와 internal token으로 재조립한다.", "evidence": [ { "start_line": 914, "end_line": 939 }, { "start_line": 1009, "end_line": 1028 } ], "assumption": false }, { "id": "oauth2-proxy", "label": "oauth2-proxy", "kind": "participant", "role": "participant", "description": "AP4_SESSION을 검증하고 인증된 user, email과 필요 시 갱신 cookie를 auth response로 돌려준다.", "evidence": [ { "start_line": 980, "end_line": 990 }, { "start_line": 1009, "end_line": 1015 } ], "assumption": false }, { "id": "spring-upstream", "label": "Spring upstream", "kind": "participant", "role": "participant", "description": "Identity header와 internal token을 함께 검증해 allowlisted identity JSON을 반환한다.", "evidence": [ { "start_line": 1017, "end_line": 1026 }, { "start_line": 1030, "end_line": 1063 } ], "assumption": false } ], "edges": [ { "id": "edge-request", "from": "browser", "to": "nginx", "label": "GET /api/edge + AP4_SESSION", "kind": "request", "order": 1, "evidence": [ { "start_line": 992, "end_line": 999 } ], "assumption": false }, { "id": "auth-subrequest", "from": "nginx", "to": "oauth2-proxy", "label": "internal /oauth2/auth subrequest", "kind": "request", "order": 2, "evidence": [ { "start_line": 922, "end_line": 939 }, { "start_line": 1009, "end_line": 1009 } ], "assumption": false }, { "id": "auth-result", "from": "oauth2-proxy", "to": "nginx", "label": "authenticated user + email", "kind": "response", "style": "dashed", "order": 3, "evidence": [ { "start_line": 1009, "end_line": 1015 } ], "assumption": false }, { "id": "upstream-request", "from": "nginx", "to": "spring-upstream", "label": "GET /edge/me · trusted headers + internal token", "kind": "request", "emphasis": "primary", "order": 4, "evidence": [ { "start_line": 1017, "end_line": 1026 } ], "assumption": false }, { "id": "identity-map", "from": "spring-upstream", "to": "nginx", "label": "trusted identity JSON", "kind": "response", "style": "dashed", "order": 5, "evidence": [ { "start_line": 1030, "end_line": 1048 } ], "assumption": false }, { "id": "browser-response", "from": "nginx", "to": "browser", "label": "pattern + user + email + identityHeader", "kind": "response", "style": "dashed", "order": 6, "evidence": [ { "start_line": 1039, "end_line": 1048 }, { "start_line": 1065, "end_line": 1076 } ], "assumption": false } ], "legend": [], "metadata": { "rationale": "로그인 redirect는 이미 앞 단계에서 설명되므로 authenticated /api/edge 요청의 trust transformation만 표현했다." } }