81 lines
7.4 KiB
Plaintext
81 lines
7.4 KiB
Plaintext
<mxfile host="Claude Code" agent="ca-superpowers + diagram-standards v2 minimalist" version="24.0.0" type="device">
|
|
<diagram name="P2A-Cluster-Internal-no-Google" id="p2a">
|
|
<mxGraphModel dx="1200" dy="700" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="780" math="0" shadow="0">
|
|
<root>
|
|
<mxCell id="0" />
|
|
<mxCell id="1" parent="0" />
|
|
|
|
<mxCell id="title" value="P2A — Cluster-internal SPA-direct (no Google)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F2937;" vertex="1" parent="1">
|
|
<mxGeometry x="40" y="20" width="800" height="32" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="subtitle" value="Edge proxy 없이 SPA가 직접 OIDC. Backend는 JWT Resource Server. JWKS 가 어떻게 신뢰를 닫는가?" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;fontStyle=0;fontFamily=Pretendard,Helvetica;fontColor=#6B7280;" vertex="1" parent="1">
|
|
<mxGeometry x="40" y="52" width="1000" height="20" as="geometry" />
|
|
</mxCell>
|
|
|
|
<!-- Cluster Internal zone -->
|
|
<mxCell id="grp-internal" value="Cluster Internal" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FBFCFD;strokeColor=#1F6FEB;strokeWidth=2;dashed=0;fontSize=12;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=left;verticalAlign=top;spacingLeft=10;spacingTop=6;" vertex="1" parent="1">
|
|
<mxGeometry x="320" y="100" width="760" height="260" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="user" value="<b>User</b> Browser + SPA" style="rounded=8;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#57606A;strokeWidth=1.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#24292F;align=center;verticalAlign=middle;" vertex="1" parent="1">
|
|
<mxGeometry x="120" y="190" width="140" height="80" as="geometry" />
|
|
</mxCell>
|
|
|
|
<!-- SPA: 주인공 (토큰 보유자) -->
|
|
<mxCell id="spa" value="<b>vanilla JS SPA</b> nginx · PKCE" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#EFF6FF;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=center;verticalAlign=middle;" vertex="1" parent="1">
|
|
<mxGeometry x="360" y="180" width="200" height="80" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="backend" value="<b>Backend RS</b> Spring Security 6.x" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#57606A;strokeWidth=1.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#24292F;align=center;verticalAlign=middle;" vertex="1" parent="1">
|
|
<mxGeometry x="640" y="140" width="200" height="80" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="keycloak" value="<b>Keycloak</b> OIDC AS + JWKS" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#57606A;strokeWidth=1.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#24292F;align=center;verticalAlign=middle;" vertex="1" parent="1">
|
|
<mxGeometry x="900" y="240" width="160" height="80" as="geometry" />
|
|
</mxCell>
|
|
|
|
<!-- EDGES -->
|
|
<mxCell id="e1" value="① HTTPS GET (SPA)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#57606A;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#24292F;" edge="1" parent="1" source="user" target="spa">
|
|
<mxGeometry relative="1" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="e2" value="② OIDC + PKCE" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.7;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" edge="1" parent="1" source="spa" target="keycloak">
|
|
<mxGeometry relative="1" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="e3" value="③ Bearer access_token" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" edge="1" parent="1" source="spa" target="backend">
|
|
<mxGeometry relative="1" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="e4" value="④ JWKS (검증 키)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.8;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" edge="1" parent="1" source="backend" target="keycloak">
|
|
<mxGeometry relative="1" as="geometry" />
|
|
</mxCell>
|
|
|
|
<!-- CALLOUT -->
|
|
<mxCell id="callout" value="⚠️ <b>SPA 토큰 보유 → XSS surface 확대</b> access/refresh token 이 브라우저 메모리/스토리지에 노출 가능. XSS 1건 = 토큰 탈취 = 사용자 세션 전체 탈취. ✅ refresh token 보호 필요 시 BFF(P1) 또는 httpOnly cookie 전략 검토." style="rounded=8;whiteSpace=wrap;html=1;fillColor=#FEF2F2;strokeColor=#DC2626;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#7F1D1D;align=left;verticalAlign=top;spacingLeft=12;spacingTop=8;" vertex="1" parent="1">
|
|
<mxGeometry x="120" y="420" width="600" height="120" as="geometry" />
|
|
</mxCell>
|
|
|
|
<!-- LEGEND -->
|
|
<mxCell id="leg-title" value="Legend" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#374151;" vertex="1" parent="1">
|
|
<mxGeometry x="120" y="580" width="100" height="20" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="leg-spa" value="파란 박스 + 파란 굵은 화살 = SPA-direct OIDC 핵심 (주인공: SPA + 토큰 흐름)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" vertex="1" parent="1">
|
|
<mxGeometry x="120" y="605" width="700" height="20" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="leg-zone" value="파란 zone = Cluster Internal (Edge proxy 없음, P1 과의 결정적 차이)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" vertex="1" parent="1">
|
|
<mxGeometry x="120" y="625" width="700" height="20" as="geometry" />
|
|
</mxCell>
|
|
|
|
<mxCell id="footer" value="v1 (minimalist) · 2026-05-26" style="text;html=1;strokeColor=none;fillColor=none;align=right;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;fontStyle=2;fontFamily=Pretendard,Helvetica;fontColor=#9CA3AF;" vertex="1" parent="1">
|
|
<mxGeometry x="900" y="730" width="200" height="20" as="geometry" />
|
|
</mxCell>
|
|
|
|
</root>
|
|
</mxGraphModel>
|
|
</diagram>
|
|
</mxfile>
|