Files
document-haness/.playwright-mcp/page-2026-08-26T11-44-15-459Z.yml
T

486 lines
37 KiB
YAML

- generic [ref=f15e3]:
- link "본문으로 건너뛰기" [ref=f15e4] [cursor=pointer]:
- /url: "#main-content"
- banner [ref=f15e5]:
- generic [ref=f15e6]:
- link "TechLog Studio" [ref=f15e7] [cursor=pointer]:
- /url: /studio
- text: TechLog
- generic [ref=f15e8]: Studio
- navigation "Studio 주 탐색" [ref=f15e10]:
- link "작업본" [ref=f15e11] [cursor=pointer]:
- /url: /studio/documents
- link "게시 기록" [ref=f15e12] [cursor=pointer]:
- /url: /studio/publications
- link "새 문서" [ref=f15e13] [cursor=pointer]:
- /url: /studio/documents/new
- link "주제·프로젝트" [ref=f15e14] [cursor=pointer]:
- /url: /studio/taxonomy
- link "릴리즈" [ref=f15e15] [cursor=pointer]:
- /url: /studio/releases
- link "공개 사이트 보기" [ref=f15e16] [cursor=pointer]:
- /url: /
- button "로그아웃" [ref=f15e17]
- main [ref=f15e18]:
- generic [ref=f15e19]:
- generic [ref=f15e20]:
- region [ref=f15e21]:
- generic [ref=f15e22]:
- paragraph [ref=f15e23]: REFERENCE · VERSION 11
- heading "문서 편집" [level=1] [ref=f15e24]
- paragraph [ref=f15e25]: OAuth/OIDC 인증 패턴 선택 기준
- region [ref=f15e26]:
- generic [ref=f15e27]:
- paragraph [ref=f15e28]: DOCUMENT
- heading "기본 정보" [level=2] [ref=f15e29]
- generic [ref=f15e30]:
- generic [ref=f15e31]:
- generic [ref=f15e32]: 제목
- textbox "제목" [ref=f15e33]: OAuth/OIDC 인증 패턴 선택 기준
- generic [ref=f15e34]:
- generic [ref=f15e35]: slug
- textbox "slug" [ref=f15e36]:
- /placeholder: 비우면 제목에서 만듭니다 (영문 소문자·숫자·하이픈)
- text: oauth-oidc-pattern-selection-criteria
- generic [ref=f15e37]:
- generic [ref=f15e38]: 요약
- textbox "요약" [ref=f15e39]: SPA, Mediator, BFF, OAuth2-Proxy는 브라우저의 access token 사용 여부, Resource Server 호출 주체, server-side 인증 상태, 보호 자원이 검증하는 credential, CSRF 처리 위치가 서로 다르다. 패턴 선택에서는 이 다섯 항목을 요구사항과 운영 환경에 맞춰 비교한다.
- generic [ref=f15e40]:
- generic [ref=f15e41]: Topic
- combobox "Topic" [ref=f15e42]:
- option "선택하지 않음"
- option "OAuth/OIDC 인증 경계" [selected]
- generic [ref=f15e43]:
- generic [ref=f15e44]: Project
- combobox "Project" [ref=f15e45]:
- option "미지정"
- option "Backend Clean Architecture"
- option "KeyCloak Patterns" [selected]
- option "Liner N + 1문제"
- group "관계" [ref=f15e46]:
- generic [ref=f15e48]:
- generic [ref=f15e49]:
- generic [ref=f15e50]: 관계 1 대상
- combobox "관계 1 대상" [ref=f15e51]:
- option "대상 선택"
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다" [disabled]
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
- option "BFF 인증 구조 설계 기준"
- option "BFF가 OAuth Token을 관리하는 조건"
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [disabled]
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [disabled]
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
- option "외부 IdP Federation과 Application 인증 경계"
- option "OAuth/OIDC 인증 패턴 선택 기준"
- option "OAuth Token과 Application Session을 구분하는 기준"
- option "Public Client와 Confidential Client 구분 기준"
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [disabled]
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [selected]
- generic [ref=f15e52]:
- generic [ref=f15e53]: 관계 1 이유
- textbox "관계 1 이유" [ref=f15e54]: 브라우저가 code 교환과 token 보관, API 호출을 모두 맡는다.
- generic [ref=f15e55]:
- button "위로" [disabled] [ref=f15e56]
- button "아래로" [ref=f15e57]
- button "삭제" [ref=f15e58]
- generic [ref=f15e59]:
- generic [ref=f15e60]:
- generic [ref=f15e61]: 관계 2 대상
- combobox "관계 2 대상" [ref=f15e62]:
- option "대상 선택"
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다" [disabled]
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
- option "BFF 인증 구조 설계 기준"
- option "BFF가 OAuth Token을 관리하는 조건"
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [disabled]
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [disabled]
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
- option "외부 IdP Federation과 Application 인증 경계"
- option "OAuth/OIDC 인증 패턴 선택 기준"
- option "OAuth Token과 Application Session을 구분하는 기준"
- option "Public Client와 Confidential Client 구분 기준"
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [selected]
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
- generic [ref=f15e63]:
- generic [ref=f15e64]: 관계 2 이유
- textbox "관계 2 이유" [ref=f15e65]: mediator가 refresh token을 관리하고 브라우저가 access token으로 API를 직접 호출하는 구성을 확인했다.
- generic [ref=f15e66]:
- button "위로" [ref=f15e67]
- button "아래로" [ref=f15e68]
- button "삭제" [ref=f15e69]
- generic [ref=f15e70]:
- generic [ref=f15e71]:
- generic [ref=f15e72]: 관계 3 대상
- combobox "관계 3 대상" [ref=f15e73]:
- option "대상 선택"
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다" [disabled]
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
- option "BFF 인증 구조 설계 기준"
- option "BFF가 OAuth Token을 관리하는 조건"
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [selected]
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [disabled]
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
- option "외부 IdP Federation과 Application 인증 경계"
- option "OAuth/OIDC 인증 패턴 선택 기준"
- option "OAuth Token과 Application Session을 구분하는 기준"
- option "Public Client와 Confidential Client 구분 기준"
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [disabled]
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
- generic [ref=f15e74]:
- generic [ref=f15e75]: 관계 3 이유
- textbox "관계 3 이유" [ref=f15e76]: BFF가 code 교환, token 보관, Resource Server 호출을 모두 처리하는 구성을 확인했다.
- generic [ref=f15e77]:
- button "위로" [ref=f15e78]
- button "아래로" [ref=f15e79]
- button "삭제" [ref=f15e80]
- generic [ref=f15e81]:
- generic [ref=f15e82]:
- generic [ref=f15e83]: 관계 4 대상
- combobox "관계 4 대상" [ref=f15e84]:
- option "대상 선택"
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다" [disabled]
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
- option "BFF 인증 구조 설계 기준"
- option "BFF가 OAuth Token을 관리하는 조건"
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [disabled]
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [selected]
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
- option "외부 IdP Federation과 Application 인증 경계"
- option "OAuth/OIDC 인증 패턴 선택 기준"
- option "OAuth Token과 Application Session을 구분하는 기준"
- option "Public Client와 Confidential Client 구분 기준"
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [disabled]
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
- generic [ref=f15e85]:
- generic [ref=f15e86]: 관계 4 이유
- textbox "관계 4 이유" [ref=f15e87]: 인증이 edge로 가면 보호 자원이 검증하는 것이 JWT에서 헤더로 바뀐다.
- generic [ref=f15e88]:
- button "위로" [ref=f15e89]
- button "아래로" [ref=f15e90]
- button "삭제" [ref=f15e91]
- generic [ref=f15e92]:
- generic [ref=f15e93]:
- generic [ref=f15e94]: 관계 5 대상
- combobox "관계 5 대상" [ref=f15e95]:
- option "대상 선택"
- option "인증 구조를 보안 성숙도 단계로 취급하지 않는다" [selected]
- option "서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가"
- option "Authorization Code Flow의 Endpoint와 Credential 이동 기준"
- option "BFF 인증 구조 설계 기준"
- option "BFF가 OAuth Token을 관리하는 조건"
- option "BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가"
- option "Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [disabled]
- option "Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가"
- option "Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [disabled]
- option "Forward-Auth에서 Identity Header를 신뢰하기 위한 조건"
- option "외부 IdP Federation을 별도의 인증 구조로 세지 않는다"
- option "외부 IdP Federation과 Application 인증 경계"
- option "OAuth/OIDC 인증 패턴 선택 기준"
- option "OAuth Token과 Application Session을 구분하는 기준"
- option "Public Client와 Confidential Client 구분 기준"
- option "Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [disabled]
- option "Refresh Token Rotation과 다중 Replica 경쟁을 어떻게 처리할 것인가"
- option "SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [disabled]
- generic [ref=f15e96]:
- generic [ref=f15e97]: 관계 5 이유
- textbox "관계 5 이유" [ref=f15e98]: 이 기준의 첫 항목을 프로젝트 결정으로 굳힌 기록이다.
- generic [ref=f15e99]:
- button "위로" [ref=f15e100]
- button "아래로" [disabled] [ref=f15e101]
- button "삭제" [ref=f15e102]
- button "관계 추가" [ref=f15e103]
- region [ref=f15e104]:
- generic [ref=f15e105]:
- paragraph [ref=f15e106]: REFERENCE
- heading "재사용할 기준" [level=2] [ref=f15e107]
- generic [ref=f15e108]:
- generic [ref=f15e109]: 목적
- textbox "목적" [ref=f15e110]: 브라우저에 token이 덜 보이는 순서는 있다. 그 순서를 보안 등급으로 쓰면 판단이 틀린다. BFF는 브라우저 token을 없애지만 server session과 공유 저장소를 만든다. Forward-Auth는 애플리케이션의 token custody를 줄이지만 edge 헤더 신뢰와 network 경계를 만든다. 새로 생긴 쪽을 감당할 수 없는 환경이면 앞 구조가 더 안전하다. 번호가 아니라 배치를 본다.
- group "규칙" [ref=f15e111]:
- generic [ref=f15e113]:
- generic [ref=f15e114]:
- generic [ref=f15e115]: 규칙 1 제목
- textbox "규칙 1 제목" [ref=f15e116]: 다섯 항목으로 구조를 비교한다
- generic [ref=f15e117]:
- generic [ref=f15e118]: 규칙 1 본문
- textbox "규칙 1 본문" [ref=f15e119]: "구조를 비교할 때는 브라우저 token 전달, Resource Server 호출 주체, server-side 상태, Resource Server의 검증 대상, CSRF 처리 위치를 확인한다. 브라우저가 access token을 받나 SPA : o Mediator : o BFF : x Forward-Auth : x 브라우저가 보호 자원을 직접 부르나 SPA : o Mediator : o BFF : x Forward-Auth : x server-side token 상태가 있나 SPA : x Mediator : o BFF : o Forward-Auth : proxy session 보호 자원이 무엇을 검증하나 SPA : 서명된 JWT Mediator : 서명된 JWT BFF : 서명된 JWT Forward-Auth : edge가 붙인 헤더 cookie가 credential이면 CSRF 검증이 어디에 붙나 SPA : 해당 없음 Mediator : session endpoint BFF : 상태 변경 endpoint Forward-Auth : proxy cookie 기준 호출 주체와 credential 저장 방식을 정한 뒤에는 401/403, token 갱신 실패, logout을 어느 계층에서 처리할지 정한다."
- generic [ref=f15e120]:
- button "위로" [disabled] [ref=f15e121]
- button "아래로" [ref=f15e122]
- button "삭제" [ref=f15e123]
- generic [ref=f15e124]:
- generic [ref=f15e125]:
- generic [ref=f15e126]: 규칙 2 제목
- textbox "규칙 2 제목" [ref=f15e127]: 피해야 할 조건을 먼저 확인한다
- generic [ref=f15e128]:
- generic [ref=f15e129]: 규칙 2 본문
- textbox "규칙 2 본문" [ref=f15e130]: 정책상 브라우저에 token을 둘 수 없으면 memory에만 두는 보관은 답이 아니다. backend 직접 경로나 헤더 덮어쓰기를 닫을 수 없으면 edge에 인증을 맡기지 않는다. 이 조건에 걸리면 다른 항목은 볼 필요가 없다.
- generic [ref=f15e131]:
- button "위로" [ref=f15e132]
- button "아래로" [ref=f15e133]
- button "삭제" [ref=f15e134]
- generic [ref=f15e135]:
- generic [ref=f15e136]:
- generic [ref=f15e137]: 규칙 3 제목
- textbox "규칙 3 제목" [ref=f15e138]: 선택 조건과 운영 부담을 함께 기록한다
- generic [ref=f15e139]:
- generic [ref=f15e140]: 규칙 3 본문
- textbox "규칙 3 본문" [ref=f15e141]: 선택 결과만 적지 않고 어떤 요구에서 해당 패턴을 선택했는지와 적용하기 어려운 조건도 함께 기록한다.
- generic [ref=f15e142]:
- button "위로" [ref=f15e143]
- button "아래로" [ref=f15e144]
- button "삭제" [ref=f15e145]
- generic [ref=f15e146]:
- generic [ref=f15e147]:
- generic [ref=f15e148]: 규칙 4 제목
- textbox "규칙 4 제목" [ref=f15e149]: 이름으로 운영 속성을 추정하지 않는다
- generic [ref=f15e150]:
- generic [ref=f15e151]: 규칙 4 본문
- textbox "규칙 4 본문" [ref=f15e152]: BFF나 forward-auth라는 이름은 배치를 말할 뿐이다. 공유 저장소와 장애 복구, session failover, secret 교체가 갖춰져 있는지는 매번 따로 확인한다.
- generic [ref=f15e153]:
- button "위로" [ref=f15e154]
- button "아래로" [ref=f15e155]
- button "삭제" [ref=f15e156]
- generic [ref=f15e157]:
- generic [ref=f15e158]:
- generic [ref=f15e159]: 규칙 5 제목
- textbox "규칙 5 제목" [ref=f15e160]: 옮기는 것은 업그레이드가 아니다
- generic [ref=f15e161]:
- generic [ref=f15e162]: 규칙 5 본문
- textbox "규칙 5 본문" [ref=f15e163]: 패턴을 바꾸면 credential을 저장하고 전달하고 검증하는 주체도 함께 바뀐다. edge header가 계속 늘어나 애플리케이션 도메인 정보까지 전달해야 한다면 BFF에서 인가와 API 조합을 처리하는 구성을 다시 검토할 수 있다.
- generic [ref=f15e164]:
- button "위로" [ref=f15e165]
- button "아래로" [disabled] [ref=f15e166]
- button "삭제" [ref=f15e167]
- button "규칙 추가" [ref=f15e168]
- group "적용 조건" [ref=f15e169]:
- generic [ref=f15e171]:
- generic [ref=f15e172]:
- generic [ref=f15e173]: 적용 조건 1
- textbox "적용 조건 1" [ref=f15e174]: 인증 구조를 처음 고를 때
- generic [ref=f15e175]:
- button "위로" [disabled] [ref=f15e176]
- button "아래로" [ref=f15e177]
- button "삭제" [ref=f15e178]
- generic [ref=f15e179]:
- generic [ref=f15e180]:
- generic [ref=f15e181]: 적용 조건 2
- textbox "적용 조건 2" [ref=f15e182]: 한 구조에서 다른 구조로 옮기려 할 때
- generic [ref=f15e183]:
- button "위로" [ref=f15e184]
- button "아래로" [ref=f15e185]
- button "삭제" [ref=f15e186]
- generic [ref=f15e187]:
- generic [ref=f15e188]:
- generic [ref=f15e189]: 적용 조건 3
- textbox "적용 조건 3" [ref=f15e190]: 구조를 문서로 비교할 때
- generic [ref=f15e191]:
- button "위로" [ref=f15e192]
- button "아래로" [ref=f15e193]
- button "삭제" [ref=f15e194]
- generic [ref=f15e195]:
- generic [ref=f15e196]:
- generic [ref=f15e197]: 적용 조건 4
- textbox "적용 조건 4" [ref=f15e198]: 이름만 보고 고른 구조를 다시 검토할 때
- generic [ref=f15e199]:
- button "위로" [ref=f15e200]
- button "아래로" [disabled] [ref=f15e201]
- button "삭제" [ref=f15e202]
- button "적용 조건 추가" [ref=f15e203]
- group "예외" [ref=f15e204]:
- generic [ref=f15e206]:
- generic [ref=f15e207]:
- generic [ref=f15e208]: 예외 1
- textbox "예외 1" [ref=f15e209]: 요구가 하나로 좁혀지면 비교가 필요 없다. 브라우저에 token을 둘 수 없고 backend가 API를 조합해야 하면 선택지는 하나다.
- generic [ref=f15e210]:
- button "위로" [disabled] [ref=f15e211]
- button "아래로" [ref=f15e212]
- button "삭제" [ref=f15e213]
- generic [ref=f15e214]:
- generic [ref=f15e215]:
- generic [ref=f15e216]: 예외 2
- textbox "예외 2" [ref=f15e217]: 학습이나 시연이 목적이면 운영 속성 비교를 하지 않아도 된다. 그때는 학습 환경이라고 문서에 적어 둔다.
- generic [ref=f15e218]:
- button "위로" [ref=f15e219]
- button "아래로" [disabled] [ref=f15e220]
- button "삭제" [ref=f15e221]
- button "예외 추가" [ref=f15e222]
- group "예시" [ref=f15e223]:
- generic [ref=f15e225]:
- generic [ref=f15e226]:
- generic [ref=f15e227]: 예시 1
- textbox "예시 1" [ref=f15e228]: "SPA : 브라우저가 code 교환과 token 보관, API 호출을 모두 맡는다"
- generic [ref=f15e229]:
- button "위로" [disabled] [ref=f15e230]
- button "아래로" [ref=f15e231]
- button "삭제" [ref=f15e232]
- generic [ref=f15e233]:
- generic [ref=f15e234]:
- generic [ref=f15e235]: 예시 2
- textbox "예시 2" [ref=f15e236]: "Mediator : refresh token은 server에 있고 access token은 응답 본문으로 브라우저에 간다"
- generic [ref=f15e237]:
- button "위로" [ref=f15e238]
- button "아래로" [ref=f15e239]
- button "삭제" [ref=f15e240]
- generic [ref=f15e241]:
- generic [ref=f15e242]:
- generic [ref=f15e243]: 예시 3
- textbox "예시 3" [ref=f15e244]: "BFF : server가 code 교환·token 관리·API 호출을 담당하고 브라우저는 session cookie로 BFF를 호출한다"
- generic [ref=f15e245]:
- button "위로" [ref=f15e246]
- button "아래로" [ref=f15e247]
- button "삭제" [ref=f15e248]
- generic [ref=f15e249]:
- generic [ref=f15e250]:
- generic [ref=f15e251]: 예시 4
- textbox "예시 4" [ref=f15e252]: "Forward-Auth : edge가 인증하고 upstream은 edge가 붙인 헤더를 본다"
- generic [ref=f15e253]:
- button "위로" [ref=f15e254]
- button "아래로" [disabled] [ref=f15e255]
- button "삭제" [ref=f15e256]
- button "예시 추가" [ref=f15e257]
- generic [ref=f15e258]:
- generic [ref=f15e259]: 마지막 검증일
- textbox "마지막 검증일" [ref=f15e260]
- region [ref=f15e261]:
- generic [ref=f15e262]:
- paragraph [ref=f15e263]: LIVE
- heading "즉시 미리보기" [level=2] [ref=f15e264]
- generic [ref=f15e267]:
- generic [ref=f15e268]:
- navigation "문서 경로" [ref=f15e269]:
- link "Reference" [ref=f15e270] [cursor=pointer]:
- /url: /explore/references
- generic [ref=f15e271]: /
- generic [ref=f15e272]: OAuth/OIDC 인증 경계
- generic [ref=f15e273]: /
- link "KeyCloak Patterns" [ref=f15e274] [cursor=pointer]:
- /url: /projects/keycloak-patterns
- heading "OAuth/OIDC 인증 패턴 선택 기준" [level=1] [ref=f15e275]
- paragraph [ref=f15e276]: SPA, Mediator, BFF, OAuth2-Proxy는 브라우저의 access token 사용 여부, Resource Server 호출 주체, server-side 인증 상태, 보호 자원이 검증하는 credential, CSRF 처리 위치가 서로 다르다. 패턴 선택에서는 이 다섯 항목을 요구사항과 운영 환경에 맞춰 비교한다.
- generic [ref=f15e277]:
- generic [ref=f15e278]:
- term [ref=f15e279]: 유형
- definition [ref=f15e280]: Reference
- generic [ref=f15e281]:
- term [ref=f15e282]: 프로젝트
- definition [ref=f15e283]: KeyCloak Patterns
- generic [ref=f15e284]:
- term [ref=f15e285]: 게시
- definition [ref=f15e286]: 게시 전
- region [ref=f15e287]:
- paragraph [ref=f15e288]: Purpose
- heading "이 기준을 쓰는 이유" [level=2] [ref=f15e289]
- paragraph [ref=f15e290]: 브라우저에 token이 덜 보이는 순서는 있다. 그 순서를 보안 등급으로 쓰면 판단이 틀린다.BFF는 브라우저 token을 없애지만 server session과 공유 저장소를 만든다. Forward-Auth는 애플리케이션의 token custody를 줄이지만 edge 헤더 신뢰와 network 경계를 만든다. 새로 생긴 쪽을 감당할 수 없는 환경이면 앞 구조가 더 안전하다.번호가 아니라 배치를 본다.
- article [ref=f15e291]:
- region [ref=f15e292]:
- heading "판단 기준" [level=2] [ref=f15e293]
- list [ref=f15e294]:
- listitem [ref=f15e295]:
- generic [ref=f15e296]: "01"
- generic [ref=f15e297]:
- heading "다섯 항목으로 구조를 비교한다" [level=3] [ref=f15e298]
- paragraph [ref=f15e299]: "구조를 비교할 때는 브라우저 token 전달, Resource Server 호출 주체, server-side 상태, Resource Server의 검증 대상, CSRF 처리 위치를 확인한다. 브라우저가 access token을 받나 SPA : o Mediator : o BFF : x Forward-Auth : x 브라우저가 보호 자원을 직접 부르나 SPA : o Mediator : o BFF : x Forward-Auth : x server-side token 상태가 있나 SPA : x Mediator : o BFF : o Forward-Auth : proxy session 보호 자원이 무엇을 검증하나 SPA : 서명된 JWT Mediator : 서명된 JWT BFF : 서명된 JWT Forward-Auth : edge가 붙인 헤더 cookie가 credential이면 CSRF 검증이 어디에 붙나 SPA : 해당 없음 Mediator : session endpoint BFF : 상태 변경 endpoint Forward-Auth : proxy cookie 기준 호출 주체와 credential 저장 방식을 정한 뒤에는 401/403, token 갱신 실패, logout을 어느 계층에서 처리할지 정한다."
- listitem [ref=f15e300]:
- generic [ref=f15e301]: "02"
- generic [ref=f15e302]:
- heading "피해야 할 조건을 먼저 확인한다" [level=3] [ref=f15e303]
- paragraph [ref=f15e304]: 정책상 브라우저에 token을 둘 수 없으면 memory에만 두는 보관은 답이 아니다. backend 직접 경로나 헤더 덮어쓰기를 닫을 수 없으면 edge에 인증을 맡기지 않는다. 이 조건에 걸리면 다른 항목은 볼 필요가 없다.
- listitem [ref=f15e305]:
- generic [ref=f15e306]: "03"
- generic [ref=f15e307]:
- heading "선택 조건과 운영 부담을 함께 기록한다" [level=3] [ref=f15e308]
- paragraph [ref=f15e309]: 선택 결과만 적지 않고 어떤 요구에서 해당 패턴을 선택했는지와 적용하기 어려운 조건도 함께 기록한다.
- listitem [ref=f15e310]:
- generic [ref=f15e311]: "04"
- generic [ref=f15e312]:
- heading "이름으로 운영 속성을 추정하지 않는다" [level=3] [ref=f15e313]
- paragraph [ref=f15e314]: BFF나 forward-auth라는 이름은 배치를 말할 뿐이다. 공유 저장소와 장애 복구, session failover, secret 교체가 갖춰져 있는지는 매번 따로 확인한다.
- listitem [ref=f15e315]:
- generic [ref=f15e316]: "05"
- generic [ref=f15e317]:
- heading "옮기는 것은 업그레이드가 아니다" [level=3] [ref=f15e318]
- paragraph [ref=f15e319]: 패턴을 바꾸면 credential을 저장하고 전달하고 검증하는 주체도 함께 바뀐다. edge header가 계속 늘어나 애플리케이션 도메인 정보까지 전달해야 한다면 BFF에서 인가와 API 조합을 처리하는 구성을 다시 검토할 수 있다.
- region [ref=f15e320]:
- heading "적용할 때" [level=2] [ref=f15e321]
- list [ref=f15e322]:
- listitem [ref=f15e323]: 인증 구조를 처음 고를 때
- listitem [ref=f15e324]: 한 구조에서 다른 구조로 옮기려 할 때
- listitem [ref=f15e325]: 구조를 문서로 비교할 때
- listitem [ref=f15e326]: 이름만 보고 고른 구조를 다시 검토할 때
- region [ref=f15e327]:
- heading "예외와 주의" [level=2] [ref=f15e328]
- list [ref=f15e329]:
- listitem [ref=f15e330]: 요구가 하나로 좁혀지면 비교가 필요 없다. 브라우저에 token을 둘 수 없고 backend가 API를 조합해야 하면 선택지는 하나다.
- listitem [ref=f15e331]: 학습이나 시연이 목적이면 운영 속성 비교를 하지 않아도 된다. 그때는 학습 환경이라고 문서에 적어 둔다.
- region [ref=f15e332]:
- heading "예시" [level=2] [ref=f15e333]
- list [ref=f15e334]:
- listitem [ref=f15e335]: "SPA : 브라우저가 code 교환과 token 보관, API 호출을 모두 맡는다"
- listitem [ref=f15e336]: "Mediator : refresh token은 server에 있고 access token은 응답 본문으로 브라우저에 간다"
- listitem [ref=f15e337]: "BFF : server가 code 교환·token 관리·API 호출을 담당하고 브라우저는 session cookie로 BFF를 호출한다"
- listitem [ref=f15e338]: "Forward-Auth : edge가 인증하고 upstream은 edge가 붙인 헤더를 본다"
- paragraph [ref=f15e339]: 마지막 검증
- region [ref=f15e340]:
- paragraph [ref=f15e341]: Relations
- heading "이 기록과 연결된 맥락" [level=2] [ref=f15e342]
- list [ref=f15e343]:
- listitem [ref=f15e344]:
- link "브라우저가 code 교환과 token 보관, API 호출을 모두 맡는다. SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계" [ref=f15e345] [cursor=pointer]:
- /url: /cases/spa-browser-credential-boundary
- generic [ref=f15e346]: 브라우저가 code 교환과 token 보관, API 호출을 모두 맡는다.
- strong [ref=f15e347]: SPA에서 토큰을 직접 관리하면서 드러난 Browser Credential 경계
- generic [ref=f15e348]:
- listitem [ref=f15e349]:
- link "mediator가 refresh token을 관리하고 브라우저가 access token으로 API를 직접 호출하는 구성을 확인했다. Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출" [ref=f15e350] [cursor=pointer]:
- /url: /cases/split-custody-access-token
- generic [ref=f15e351]: mediator가 refresh token을 관리하고 브라우저가 access token으로 API를 직접 호출하는 구성을 확인했다.
- strong [ref=f15e352]: Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출
- generic [ref=f15e353]:
- listitem [ref=f15e354]:
- link "BFF가 code 교환, token 보관, Resource Server 호출을 모두 처리하는 구성을 확인했다. Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정" [ref=f15e355] [cursor=pointer]:
- /url: /cases/bff-session-csrf-responsibility
- generic [ref=f15e356]: BFF가 code 교환, token 보관, Resource Server 호출을 모두 처리하는 구성을 확인했다.
- strong [ref=f15e357]: Browser Token을 없애면서 BFF에 Session과 CSRF 책임이 생긴 과정
- generic [ref=f15e358]:
- listitem [ref=f15e359]:
- link "인증이 edge로 가면 보호 자원이 검증하는 것이 JWT에서 헤더로 바뀐다. Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유" [ref=f15e360] [cursor=pointer]:
- /url: /cases/identity-header-trust
- generic [ref=f15e361]: 인증이 edge로 가면 보호 자원이 검증하는 것이 JWT에서 헤더로 바뀐다.
- strong [ref=f15e362]: Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유
- generic [ref=f15e363]:
- complementary [ref=f15e364]:
- heading "작업 상태" [level=2] [ref=f15e365]
- status "편집 상태" [ref=f15e366]: 저장됨
- generic [ref=f15e367]:
- generic [ref=f15e368]:
- term [ref=f15e369]: 저장 버전
- definition [ref=f15e370]: "11"
- generic [ref=f15e371]:
- term [ref=f15e372]: 종류
- definition [ref=f15e373]: REFERENCE
- paragraph [ref=f15e374]: 불완전한 초안도 저장할 수 있습니다. Ctrl+S 로도 저장합니다. 게시를 누르면 채워야 할 칸을 그 자리에 표시합니다.
- generic [ref=f15e375]:
- button "저장" [disabled] [ref=f15e376]
- button "게시" [ref=f15e377]
- paragraph [ref=f15e378]: 버전 11으로 저장했습니다.