259 lines
19 KiB
YAML
259 lines
19 KiB
YAML
- generic [ref=f4e3]:
|
|
- link "본문으로 건너뛰기" [ref=f4e4] [cursor=pointer]:
|
|
- /url: "#main-content"
|
|
- banner [ref=f4e5]:
|
|
- generic [ref=f4e6]:
|
|
- link "TechLog Studio" [ref=f4e7] [cursor=pointer]:
|
|
- /url: /studio
|
|
- text: TechLog
|
|
- generic [ref=f4e8]: Studio
|
|
- navigation "Studio 주 탐색" [ref=f4e10]:
|
|
- link "작업본" [ref=f4e11] [cursor=pointer]:
|
|
- /url: /studio/documents
|
|
- link "게시 기록" [ref=f4e12] [cursor=pointer]:
|
|
- /url: /studio/publications
|
|
- link "새 문서" [ref=f4e13] [cursor=pointer]:
|
|
- /url: /studio/documents/new
|
|
- link "주제·프로젝트" [ref=f4e14] [cursor=pointer]:
|
|
- /url: /studio/taxonomy
|
|
- link "릴리즈" [ref=f4e15] [cursor=pointer]:
|
|
- /url: /studio/releases
|
|
- link "공개 사이트 보기" [ref=f4e16] [cursor=pointer]:
|
|
- /url: /
|
|
- button "로그아웃" [ref=f4e17]
|
|
- main [ref=f4e18]:
|
|
- generic [ref=f4e19]:
|
|
- generic [ref=f4e20]:
|
|
- region [ref=f4e21]:
|
|
- generic [ref=f4e22]:
|
|
- paragraph [ref=f4e23]: PROJECT_DECISION · VERSION 10
|
|
- heading "문서 편집" [level=1] [ref=f4e24]
|
|
- paragraph [ref=f4e25]: 외부 IdP Federation을 별도의 인증 구조로 세지 않는다
|
|
- region [ref=f4e26]:
|
|
- generic [ref=f4e27]:
|
|
- paragraph [ref=f4e28]: DOCUMENT
|
|
- heading "기본 정보" [level=2] [ref=f4e29]
|
|
- generic [ref=f4e30]:
|
|
- generic [ref=f4e31]:
|
|
- generic [ref=f4e32]: 제목
|
|
- textbox "제목" [ref=f4e33]: 외부 IdP Federation을 별도의 인증 구조로 세지 않는다
|
|
- generic [ref=f4e34]:
|
|
- generic [ref=f4e35]: slug
|
|
- textbox "slug" [ref=f4e36]:
|
|
- /placeholder: 비우면 제목에서 만듭니다 (영문 소문자·숫자·하이픈)
|
|
- text: federation-is-not-an-application-pattern
|
|
- generic [ref=f4e37]:
|
|
- generic [ref=f4e38]: 요약
|
|
- textbox "요약" [ref=f4e39]: Google은 upstream IdP, Keycloak은 애플리케이션이 신뢰하는 issuer이자 broker, 네 구조는 애플리케이션 credential 경계다. 세 층을 분리해서 적고 소셜 로그인 추가를 인증 구조 변경으로 세지 않는다.
|
|
- generic [ref=f4e40]:
|
|
- generic [ref=f4e41]: Topic
|
|
- combobox "Topic" [ref=f4e42]:
|
|
- option "선택하지 않음"
|
|
- option "OAuth/OIDC 인증 경계" [selected]
|
|
- generic [ref=f4e43]:
|
|
- generic [ref=f4e44]: Project
|
|
- combobox "Project" [ref=f4e45]:
|
|
- option "미지정"
|
|
- option "Backend Clean Architecture"
|
|
- option "KeyCloak Patterns" [selected]
|
|
- option "Liner N + 1문제"
|
|
- group "근거 기록" [ref=f4e46]:
|
|
- generic [ref=f4e48]:
|
|
- generic [ref=f4e49]:
|
|
- generic [ref=f4e50]: 근거 1 대상
|
|
- combobox "근거 1 대상" [ref=f4e51]:
|
|
- option "대상 선택"
|
|
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다"
|
|
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
|
|
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
|
|
- option "BFF 인증 구조 설계 기준"
|
|
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
|
|
- option "Browser에서 OAuth Token을 제거해야 하는 경우 BFF가 Token을 소유한다"
|
|
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정"
|
|
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
|
|
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유"
|
|
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
|
|
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
|
|
- option "외부 IdP Federation과 Application 인증 경계" [selected]
|
|
- option "OAuth/OIDC 인증 패턴 선택 기준"
|
|
- option "OAuth Token과 Application Session을 구분하는 기준" [disabled]
|
|
- option "Public Client와 Confidential Client 구분 기준"
|
|
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출"
|
|
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
|
|
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
|
|
- generic [ref=f4e52]:
|
|
- generic [ref=f4e53]: 근거 1 이유
|
|
- textbox "근거 1 이유" [ref=f4e54]: 이 결정을 규칙으로 편 기준이다.
|
|
- generic [ref=f4e55]:
|
|
- button "위로" [disabled] [ref=f4e56]
|
|
- button "아래로" [ref=f4e57]
|
|
- button "삭제" [ref=f4e58]
|
|
- generic [ref=f4e59]:
|
|
- generic [ref=f4e60]:
|
|
- generic [ref=f4e61]: 근거 2 대상
|
|
- combobox "근거 2 대상" [ref=f4e62]:
|
|
- option "대상 선택"
|
|
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다"
|
|
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
|
|
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
|
|
- option "BFF 인증 구조 설계 기준"
|
|
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
|
|
- option "Browser에서 OAuth Token을 제거해야 하는 경우 BFF가 Token을 소유한다"
|
|
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정"
|
|
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
|
|
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유"
|
|
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
|
|
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
|
|
- option "외부 IdP Federation과 Application 인증 경계" [disabled]
|
|
- option "OAuth/OIDC 인증 패턴 선택 기준"
|
|
- option "OAuth Token과 Application Session을 구분하는 기준" [disabled]
|
|
- option "Public Client와 Confidential Client 구분 기준"
|
|
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출"
|
|
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
|
|
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [selected]
|
|
- generic [ref=f4e63]:
|
|
- generic [ref=f4e64]: 근거 2 이유
|
|
- textbox "근거 2 이유" [ref=f4e65]: 브로커가 발급한 code를 받는 애플리케이션 경계다.
|
|
- generic [ref=f4e66]:
|
|
- button "위로" [ref=f4e67]
|
|
- button "아래로" [ref=f4e68]
|
|
- button "삭제" [ref=f4e69]
|
|
- generic [ref=f4e70]:
|
|
- generic [ref=f4e71]:
|
|
- generic [ref=f4e72]: 근거 3 대상
|
|
- combobox "근거 3 대상" [ref=f4e73]:
|
|
- option "대상 선택"
|
|
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다"
|
|
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
|
|
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
|
|
- option "BFF 인증 구조 설계 기준"
|
|
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
|
|
- option "Browser에서 OAuth Token을 제거해야 하는 경우 BFF가 Token을 소유한다"
|
|
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정"
|
|
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
|
|
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유"
|
|
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
|
|
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
|
|
- option "외부 IdP Federation과 Application 인증 경계" [disabled]
|
|
- option "OAuth/OIDC 인증 패턴 선택 기준"
|
|
- option "OAuth Token과 Application Session을 구분하는 기준" [selected]
|
|
- option "Public Client와 Confidential Client 구분 기준"
|
|
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출"
|
|
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
|
|
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
|
|
- generic [ref=f4e74]:
|
|
- generic [ref=f4e75]: 근거 3 이유
|
|
- textbox "근거 3 이유" [ref=f4e76]: upstream IdP 상태와 애플리케이션 상태를 같은 이름으로 부르지 않는다.
|
|
- generic [ref=f4e77]:
|
|
- button "위로" [ref=f4e78]
|
|
- button "아래로" [disabled] [ref=f4e79]
|
|
- button "삭제" [ref=f4e80]
|
|
- button "근거 추가" [ref=f4e81]
|
|
- region [ref=f4e82]:
|
|
- generic [ref=f4e83]:
|
|
- paragraph [ref=f4e84]: PROJECT DECISION
|
|
- heading "프로젝트 결정" [level=2] [ref=f4e85]
|
|
- generic [ref=f4e86]:
|
|
- generic [ref=f4e87]:
|
|
- generic [ref=f4e88]: 결정 상태
|
|
- combobox "결정 상태" [ref=f4e89]:
|
|
- option "아직 정하지 않음"
|
|
- option "PROPOSED"
|
|
- option "ADOPTED" [selected]
|
|
- generic [ref=f4e90]:
|
|
- generic [ref=f4e91]: 결정일
|
|
- textbox "결정일" [ref=f4e92]: 2026-08-24
|
|
- generic [ref=f4e93]:
|
|
- generic [ref=f4e94]: 결정문
|
|
- textbox "결정문" [ref=f4e95]: 외부 IdP federation을 다섯 번째 인증 구조로 세지 않는다. Google은 upstream IdP, Keycloak은 애플리케이션이 신뢰하는 issuer이자 broker, 네 구조는 애플리케이션 credential 경계로 각각 분리해 적는다.
|
|
- generic [ref=f4e96]:
|
|
- generic [ref=f4e97]: 판단 이유
|
|
- textbox "판단 이유" [ref=f4e98]: Google을 구조 하나로 세게 되면 upstream IdP 경계와 애플리케이션 OAuth 경계를 같은 기준으로 묶게 되는데, 두 경계는 검증 방법이 서로 다르다. 사용자가 Keycloak 로그인 화면에서 Google을 고르면 브라우저가 Google authorization endpoint로 이동한다. Keycloak은 Google의 응답을 검증해 local identity와 연결한 뒤 자기 authorization code를 애플리케이션 callback으로 보낸다. 이후 애플리케이션은 Google이 아니라 Keycloak을 상대로 code를 token으로 교환한다. Resource Server가 검증하는 issuer도 브로커이고 애플리케이션은 Google token을 받지 않기 때문에, 소셜 로그인을 붙여도 브라우저가 token을 받는지와 어느 계층이 API를 부르는지는 하나도 바뀌지 않는다. 두 경계를 섞어 두게 되면 비교표에 성격이 다른 항목이 끼어들고, 계정 연결 규칙도 인증 구조 이야기에 섞여서 따로 설계하지 않고 넘어가게 된다.
|
|
- group "영향" [ref=f4e99]:
|
|
- generic [ref=f4e101]:
|
|
- generic [ref=f4e102]:
|
|
- generic [ref=f4e103]: 영향 1
|
|
- textbox "영향 1" [ref=f4e104]: Google을 추가해도 애플리케이션이 검증하는 issuer는 Keycloak으로 유지한다. 네 구조의 credential 배치 기준은 바뀌지 않는다.
|
|
- generic [ref=f4e105]:
|
|
- button "위로" [disabled] [ref=f4e106]
|
|
- button "아래로" [ref=f4e107]
|
|
- button "삭제" [ref=f4e108]
|
|
- generic [ref=f4e109]:
|
|
- generic [ref=f4e110]:
|
|
- generic [ref=f4e111]: 영향 2
|
|
- textbox "영향 2" [ref=f4e112]: 계정 연결을 별도 문제로 다뤄야 하고, provider와 upstream subject의 조합을 열쇠로 쓰면서 email이 같다고 자동 병합하지 않는다.
|
|
- generic [ref=f4e113]:
|
|
- button "위로" [ref=f4e114]
|
|
- button "아래로" [ref=f4e115]
|
|
- button "삭제" [ref=f4e116]
|
|
- generic [ref=f4e117]:
|
|
- generic [ref=f4e118]:
|
|
- generic [ref=f4e119]: 영향 3
|
|
- textbox "영향 3" [ref=f4e120]: 검증 범위를 두 겹으로 적어야 해서 mock provider로 확인한 broker·claim mapping 계약과 실제 계정·공개 HTTPS callback·consent를 구분하게 된다.
|
|
- generic [ref=f4e121]:
|
|
- button "위로" [ref=f4e122]
|
|
- button "아래로" [ref=f4e123]
|
|
- button "삭제" [ref=f4e124]
|
|
- generic [ref=f4e125]:
|
|
- generic [ref=f4e126]:
|
|
- generic [ref=f4e127]: 영향 4
|
|
- textbox "영향 4" [ref=f4e128]: upstream IdP가 늘면 브로커 설정이 늘어나게 되어서 그 설정의 소유자를 애플리케이션 팀과 따로 정해야 한다.
|
|
- generic [ref=f4e129]:
|
|
- button "위로" [ref=f4e130]
|
|
- button "아래로" [disabled] [ref=f4e131]
|
|
- button "삭제" [ref=f4e132]
|
|
- button "영향 추가" [ref=f4e133]
|
|
- region [ref=f4e134]:
|
|
- generic [ref=f4e135]:
|
|
- paragraph [ref=f4e136]: LIVE
|
|
- heading "즉시 미리보기" [level=2] [ref=f4e137]
|
|
- generic [ref=f4e140]:
|
|
- navigation "문서 경로" [ref=f4e141]:
|
|
- link "Project" [ref=f4e142] [cursor=pointer]:
|
|
- /url: /projects
|
|
- generic [ref=f4e143]: /
|
|
- link "KeyCloak Patterns" [ref=f4e144] [cursor=pointer]:
|
|
- /url: /projects/keycloak-patterns
|
|
- generic [ref=f4e145]: /
|
|
- link "Decision" [ref=f4e146] [cursor=pointer]:
|
|
- /url: /projects/keycloak-patterns/decisions
|
|
- list [ref=f4e147]:
|
|
- listitem [ref=f4e148]:
|
|
- article [ref=f4e149]:
|
|
- generic [ref=f4e150]:
|
|
- generic [ref=f4e151]:
|
|
- generic [ref=f4e152]: ADOPTED
|
|
- time [ref=f4e153]: 2026.08.24
|
|
- heading "외부 IdP Federation을 별도의 인증 구조로 세지 않는다" [level=2] [ref=f4e154]
|
|
- paragraph [ref=f4e155]: 외부 IdP federation을 다섯 번째 인증 구조로 세지 않는다.Google은 upstream IdP, Keycloak은 애플리케이션이 신뢰하는 issuer이자 broker, 네 구조는 애플리케이션 credential 경계로 각각 분리해 적는다.
|
|
- generic [ref=f4e156]:
|
|
- heading "판단 이유" [level=3] [ref=f4e157]
|
|
- paragraph [ref=f4e158]: Google을 구조 하나로 세게 되면 upstream IdP 경계와 애플리케이션 OAuth 경계를 같은 기준으로 묶게 되는데, 두 경계는 검증 방법이 서로 다르다.사용자가 Keycloak 로그인 화면에서 Google을 고르면 브라우저가 Google authorization endpoint로 이동한다. Keycloak은 Google의 응답을 검증해 local identity와 연결한 뒤 자기 authorization code를 애플리케이션 callback으로 보낸다. 이후 애플리케이션은 Google이 아니라 Keycloak을 상대로 code를 token으로 교환한다.Resource Server가 검증하는 issuer도 브로커이고 애플리케이션은 Google token을 받지 않기 때문에, 소셜 로그인을 붙여도 브라우저가 token을 받는지와 어느 계층이 API를 부르는지는 하나도 바뀌지 않는다.두 경계를 섞어 두게 되면 비교표에 성격이 다른 항목이 끼어들고, 계정 연결 규칙도 인증 구조 이야기에 섞여서 따로 설계하지 않고 넘어가게 된다.
|
|
- generic [ref=f4e159]:
|
|
- heading "영향" [level=3] [ref=f4e160]
|
|
- list [ref=f4e161]:
|
|
- listitem [ref=f4e162]: Google을 추가해도 애플리케이션이 검증하는 issuer는 Keycloak으로 유지한다. 네 구조의 credential 배치 기준은 바뀌지 않는다.
|
|
- listitem [ref=f4e163]: 계정 연결을 별도 문제로 다뤄야 하고, provider와 upstream subject의 조합을 열쇠로 쓰면서 email이 같다고 자동 병합하지 않는다.
|
|
- listitem [ref=f4e164]: 검증 범위를 두 겹으로 적어야 해서 mock provider로 확인한 broker·claim mapping 계약과 실제 계정·공개 HTTPS callback·consent를 구분하게 된다.
|
|
- listitem [ref=f4e165]: upstream IdP가 늘면 브로커 설정이 늘어나게 되어서 그 설정의 소유자를 애플리케이션 팀과 따로 정해야 한다.
|
|
- generic [ref=f4e166]:
|
|
- heading "근거 기록" [level=3] [ref=f4e167]
|
|
- list [ref=f4e168]:
|
|
- listitem [ref=f4e169]:
|
|
- link "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [ref=f4e170] [cursor=pointer]:
|
|
- /url: /cases/spa-browser-credential-boundary
|
|
- complementary [ref=f4e171]:
|
|
- heading "작업 상태" [level=2] [ref=f4e172]
|
|
- status "편집 상태" [ref=f4e173]: 저장됨
|
|
- generic [ref=f4e174]:
|
|
- generic [ref=f4e175]:
|
|
- term [ref=f4e176]: 저장 버전
|
|
- definition [ref=f4e177]: "10"
|
|
- generic [ref=f4e178]:
|
|
- term [ref=f4e179]: 종류
|
|
- definition [ref=f4e180]: Decision
|
|
- paragraph [ref=f4e181]: 불완전한 초안도 저장할 수 있습니다. Ctrl+S 로도 저장합니다. 게시를 누르면 채워야 할 칸을 그 자리에 표시합니다.
|
|
- generic [ref=f4e182]:
|
|
- button "저장" [disabled] [ref=f4e183]
|
|
- button "게시" [ref=f4e184]
|
|
- paragraph [ref=f4e185]: 버전 10으로 저장했습니다. |