36 KiB
title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, tags, created, target_merge, status_label, contract_packet_sha256
| title | source_type | status | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | branch | parent_branch | related_projects | tags | created | target_merge | status_label | contract_packet_sha256 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-keycloak-first-broker-login-flow (First Broker Login Flow — Confirm Link Existing Account) | branch-note | raw | BR-KEYCLOAK-PATTERNS-OVERVIEW-016 | project-work-item | keycloak-patterns-overview | WI-KEYCLOAK-PATTERNS-OVERVIEW-016 |
|
|
1 | feature-keycloak-first-broker-login-flow |
|
|
2026-05-25 | in-progress | 342adc2532438c3f05c868020a6cc7fdfc2a3322fddceed4180f75fd258fd6c0 |
branch: feature-keycloak-first-broker-login-flow (First Broker Login Flow — Confirm Link Existing Account)
Layer:
raw/branch-notes/— raw/project-notes/keycloak-patterns-overview의WI-KEYCLOAK-PATTERNS-OVERVIEW-016직접 branch. 분류축 교정 반영 (hub 2026-07-14): 신 primary 축에서 본 branch 는 Google IdP brokering cross-cutting 그룹 (hub §8.0 그룹 5) 의 Tier-2 구현 branch다. done-bar (hub §1 성공기준 cross / §8.0 그룹 5):email_verified=falseauto-linking 계정탈취 재현 → Confirm Link Existing Account 로 차단, before/after 기록, 목표 등급locally-verified. (기존 "documented-only / 실 구현 안 함" 프레이밍은 2026-07-14 재편으로 stale — §AuditFRAMING_DRIFT참조.)status_label:in-progress
부모 (필수)
raw/project-notes/keycloak-patterns-overview
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1 |
Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | First Broker Login의 계정 연결 방어 흐름에 적용한다 | raw/project-notes/keycloak-patterns-overview |
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1 |
done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | unsafe auto-linking의 재현과 차단 evidence를 완료 조건으로 사용한다 | raw/project-notes/keycloak-patterns-overview |
브랜치 지역 결정
기존 branch-local 결정은 아래
## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|
선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|
없음.
목표
Keycloak의 기본 First Broker Login Flow는 "Automatically Link Existing Account by Email" 옵션을 포함한다. 이는 편의성을 위해 보안을 희생한 default이며, Google이 email_verified=false인 사용자도 발급할 수 있는 상황을 고려하면 account takeover 위험이 있다.
본 노트는 "Confirm Link Existing Account" 변형 flow로 변경하는 방법과 그 의미를 정리한다.
⚠️ 2026-07-16 조사 정정 (위 전제 수정): "기본 flow 가 auto-link 를 포함한다"는 부정확하다. OOTB Default First Broker Login flow 는
Create User If Unique(충돌 감지 key = email/username,KC-FBLVERIFY-C5) →Handle Existing Account(= Confirm Link Existing Account + Verify Existing Account) 경로가 이미 기본값이고, email 로 자동 link 하는Automatically Set Existing User(AutoLink) 는 별도로 추가해야 하는 opt-in dangerous authenticator 다(공식 WARNINGKC-FBLVERIFY-C4). 따라서 본 branch 의 done-bar 는 "기본에서 auto-link 를 제거"가 아니라 함정을 재현하려면 AutoLink 를 명시 추가한 뒤, 기본 Confirm Link 로 되돌려 차단하는 것이다(§구현 가이드, §AuditCLAIM_DRIFT). 원문은 verbatim 보존.
위험 시나리오 (Auto Link 사용 시):
- 공격자가 자신의 Google 계정 email을
victim@example.com으로 위장 (Google이email_verified=false로 발급) - Keycloak에 이미
victim@example.com으로 가입된 local 계정 존재 - Auto Link가 email match만 보고 두 계정을 link → 공격자가 Google 로그인으로 피해자 계정 접근
해결: "Confirm Link Existing Account" flow는 link 전에 사용자가 기존 Keycloak 계정 password를 입력(또는 email 확인)해야 하므로, Google 계정만으로는 link 불가.
- 이슈: (없음 — 학습 프로젝트)
- PR: (없음 — 코드 repo
/home/donghyeon/workspace/keycloak-patterns/아직 미생성, §AuditNO_GROUND_TRUTH)
범위
포함 범위
- First Broker Login Flow 의 구성 (authenticator step 값) — 이 branch 가 owner (sibling raw/branch-notes/feature-keycloak-account-linking-sub-vs-email 이 flow 구성을 본 branch 로 위임):
- D1:
Automatically Set Existing User(AutoLink) 미사용/DISABLED, 기본 Confirm Link 경로 유지. - D2:
Confirm Link Existing Account+Verify Existing Account(Email 기본 / Re-authentication fallback) 강제. - D3:
Review Profile모드 결정 (Off 권장). - D4:
email_verified=falsesilent auto-link 차단 (= core D1+D2). raw/branch-notes/feature-keycloak-idp-brokering-google-client D6 (trustEmail=false)는 defense-in-depth로만 consume.
- D1:
- 함정 재현 → 차단 E2E 절차 (done-bar): AutoLink 로 계정탈취 재현 → Confirm Link 로 차단, before/after 기록.
제외 범위
의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.
- Account linking primary key (
subvs email) 선택 → raw/branch-notes/feature-keycloak-account-linking-sub-vs-email D1 (owner). trustEmailIdP 설정값 / Google client 등록 / discovery → raw/branch-notes/feature-keycloak-idp-brokering-google-client (owner; D6 =trustEmail=false).- Google claim → attribute mapper 구성 / Sync Mode 값 → raw/branch-notes/feature-keycloak-google-claim-attribute-mapping.
- SPA 측 Confirm Link redirect/return UX → raw/branch-notes/feature-keycloak-account-linking-spa-ux.
sub기반 충돌 감지 전용 custom authenticator — OOTBCreate User If Unique는 email/username 매칭(KC-FBLVERIFY-C5). sub-only 매칭·email_verifiedhard-reject 는 커스텀 SPI authenticator 필요 → hub §5 Deferred(server-side SPI 트랙) (§AuditOUT_OF_BRANCH_SCOPE).- 비-Google IdP / SAML federation.
근거 (필수, 최소 1개+)
| Source | 정당화하는 결정 |
|---|---|
| raw/official-docs/keycloak-first-login-flow | D1(auto-link = "potential security hole" 공식 경고 KC-FLF-C2), D2(Confirm Link info page review/link 선택 KC-FLF-C3), D3(Review Profile 3모드 On/missing/Off KC-FLF-C4) |
| raw/official-docs/keycloak-first-broker-login-verify-authenticators-official | D1(AutoLink 공식 WARNING KC-FBLVERIFY-C4 + OOTB 충돌감지 key=email/username KC-FBLVERIFY-C5), D2(Verify Existing Account By Email = SMTP 시 ALTERNATIVE 기본 KC-FBLVERIFY-C1, 재인증 관철=email DISABLE KC-FBLVERIFY-C2, Re-auth=fallback KC-FBLVERIFY-C3) |
| raw/official-docs/google-openid-connect-oidc | D3(email claim 은 email scope 시 제공 GOIDC-C4); D4 전제(email_verified 발급 조건은 본 인용 범위 밖 → Claims To Verify) |
| raw/company-tech-blogs/keycloak-google-login-codemancers | D2 corroboration — 실무 Confirm flow 적용 사례 (company-case-study, 공식 best practice 로 단정 금지) |
| raw/official-docs/keycloak-identity-brokering-overview-official | First Login Flow Override(IdP 별 flow 지정) 메커니즘 배경 |
(위임) raw/branch-notes/feature-keycloak-idp-brokering-google-client D6 |
trustEmail=false — D4 email_verified 방어의 IdP 설정 lever (본 branch 재진술 금지, 참조만) |
(위임) raw/branch-notes/feature-keycloak-account-linking-sub-vs-email D1 |
sub 기반 linking key — 본 flow 가 정합해야 할 linking 정책 |
TODO
각 항목 옆에 증거 등급. 본 branch 는 hub §8.0 그룹 5 의 Tier-2 구현 branch (목표 locally-verified) — 코드 repo 생성 전까지 대부분 planned.
- First Broker Login Flow 기본 구조 정리 — 등급:
documented-onlyReview Profile(신규 사용자 프로필 확인 페이지)Create User If Unique(federated identity 없으면 신규 user 생성)Automatically Link Existing Account(기본 옵션 — 본 노트가 제거 대상)Handle Existing Account(수동 confirm 서브플로우)
- Authentication → Flows → "First Broker Login" 복제 — 등급:
planned- 기본 flow는 read-only →
Copy로 사본 생성 후 편집
- 기본 flow는 read-only →
- "Automatically Link Existing Account" 단계 제거 또는
DISABLED— 등급:planned- 해당 step의 requirement를
DISABLED로 설정
- 해당 step의 requirement를
- "Confirm Link Existing Account" 단계
REQUIRED활성화 — 등급:planned- 사용자에게 기존 계정 link 여부 확인 페이지 표시
- 이후
Verify Existing Account by Re-authenticationstep에서 password 입력
- Identity Provider 설정에서 변경된 flow를
First Login Flow Override로 지정 — 등급:planned - Review Profile flow 정책 결정 — 등급:
documented-only- Google이
email/name/picture제공 → 신규 사용자 확인 페이지 불필요한 경우 OFF - GDPR 등 동의 페이지 필요한 경우 ON
- Google이
email_verified=falsesilent auto-link 차단 정책 — 등급:documented-only- 현재 채택 범위는 D1+D2의 소유 증명 없는 자동 link 차단까지다.
- flow 진입 즉시 link/생성을 모두 거부하는 hard-reject는 구현된 custom SPI artifact가 없으므로 본 branch에서 보장하지 않는다(별도 SPI variant로 유보).
⚠️ 2026-07-16 조사 정정 (위 항목 전제 수정): (a) TODO 3 "기본에서 auto-link 제거" 는 부정확 — OOTB 기본은 이미 Confirm Link 이고 AutoLink 는 별도 opt-in(
KC-FBLVERIFY-C4/C5). 재현 시 추가 후 제거로 재구성(§구현 가이드). (b) TODO 4 "Verify Existing Account by Re-authentication REQUIRED" 는 부정확 — SMTP 설정 realm 은 "Verify Existing Account By Email"(ALTERNATIVE)이 기본, 재인증 관철은 email authenticator 명시 DISABLE 필요(KC-FBLVERIFY-C1/C2/C3). 원 TODO 는 verbatim 보존, 정정은 §Decision Evidence Map Open Risk + §Audit 를 따른다.
진행 중 메모
- Keycloak 공식 문서가 명시적으로 경고: "automatic linking by email = potential security hole" (raw/official-docs/keycloak-first-login-flow
KC-FLF-C2); AutoLink authenticator 별도 WARNING (raw/official-docs/keycloak-first-broker-login-verify-authenticators-officialKC-FBLVERIFY-C4). - "Confirm Link Existing Account" flow는 사용자 UX에 한 단계 추가됨 (link 확인 페이지 + password 재입력 또는 email 확인) — 보안 trade-off로 수용.
- 신규 사용자 (기존 Keycloak 계정 없음) 흐름은 변경 없음:
Create User If Unique→ 신규 user 생성 → (선택) Review Profile. - 본 flow 변경은 Google IdP에만 적용 가능 (IdP별 First Login Flow Override 지원). 다른 IdP에 다른 flow 적용 가능.
결정 사항
추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 원 결정문 verbatim 보존 — 조사 정정은 §Decision Evidence Map Open Risk + §Audit & Findings (CLAUDE.md §11: 사용자 결정 자동 rewrite 금지, 정합 권고만).
- 2026-05-25: 기본 First Broker Login Flow의
Automatically Link Existing Accountstep을 비활성화 (DISABLED). 보안 위험 회피. - 2026-05-25:
Confirm Link Existing Account+Verify Existing Account by Re-authenticationstep을REQUIRED로 활성화. 사용자가 기존 계정 password를 입력해야 link 완료. - 2026-05-25: Review Profile flow는
OFF권장 (Google이 profile 제공). 단, 동의 페이지 비즈니스 요건 있을 시ON. - 2026-05-25 (historical, superseded):
Googleemail_verified=false인 사용자는 link 시도 자체를 차단 (custom authenticator 또는 mapper로 강제 검증). - 2026-07-18: 현재 채택 정책은 silent auto-link 방지다.
email_verified=false전체 hard-reject는 custom SPI가 실제 구현·검증된 별도 variant에서만 활성화한다.
결정-근거 매핑
각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시한다.
Decision ID는 이 branch-note 안에서 안정적으로 유지한다 — 형제 raw/branch-notes/feature-keycloak-account-linking-sub-vs-email 가 본 branch 의D1/D2/D4를 참조하므로 ID 불변.Supporting Claims는raw/<category>/<slug>.md#<CLAIM-ID>형식.선택 조건(R2): 이 조건일 때 이 결정 / 다른 조건이면 어떤 대안.
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | Automatically Set Existing User(AutoLink) 미사용 / DISABLED — 기본 Handle Existing Account(Confirm Link) 경로 유지. 정정: OOTB 기본은 이미 Confirm Link, AutoLink 는 별도 opt-in dangerous authenticator |
운영 flow 는 항상 이 결정 — 사용자가 임의 username/email 로 자체 등록 가능한 환경에서 AutoLink 는 공식 위험(KC-FBLVERIFY-C4). 대안(AutoLink 사용)은 관리자가 등록을 엄격히 curating + username/email 을 배정하는 환경에서만. 함정 재현 시에만 AutoLink 명시 추가(§구현 가이드 §1) |
raw/official-docs/keycloak-first-login-flow.md#KC-FLF-C2 (auto-link = potential security hole), raw/official-docs/keycloak-first-broker-login-verify-authenticators-official.md#KC-FBLVERIFY-C4 (AutoLink WARNING), #KC-FBLVERIFY-C5 (OOTB 충돌감지 key = email/username) |
official-vendor-doc |
재현용 AutoLink authenticator 의 정확한 명칭/추가 위치는 admin UI 확인 필요(Claims To Verify #1). 코드 repo 부재 → planned |
| D2 | 기존 Keycloak local 계정에 Google federated identity link 시 → Confirm Link Existing Account + Verify Existing Account 강제. 정정: SMTP 설정 realm 은 "Verify Existing Account By Email"(ALTERNATIVE)이 기본 — password 재인증을 관철하려면 admin 이 email authenticator 를 명시 DISABLE |
security-first(secret 소유 증명 필요) → email authenticator DISABLE → Re-authentication. SMTP 미설정 realm → Re-authentication 자동 폴백. 소비자 서비스(마찰·지원부담 최소) → Email 검증 기본값 유지 가능(단 secret 미증명) | raw/official-docs/keycloak-first-login-flow.md#KC-FLF-C3 (info page review vs link 선택), raw/official-docs/keycloak-first-broker-login-verify-authenticators-official.md#KC-FBLVERIFY-C1 (Email=SMTP 시 기본), #KC-FBLVERIFY-C2 (재인증 관철=email DISABLE), #KC-FBLVERIFY-C3 (Re-auth=폴백); raw/company-tech-blogs/keycloak-google-login-codemancers.md (사례 corroboration) |
official-vendor-doc (+ company-case-study) |
Google-first 가입(비밀번호 미설정) 사용자는 Re-authentication 으로 재인증 수단 없어 lockout 가능 — 사용자 population 조사 필요(needs-confirmation) |
| D3 | Review Profile = Off 권장 (Google 이 profile 제공). 비즈니스 동의 요건 시 On |
Google 이 email/name 제공(profile scope) → Off. mandatory 정보(email/first/last name) 미제공 IdP → missing. GDPR 등 동의 페이지 필요 → On |
raw/official-docs/keycloak-first-login-flow.md#KC-FLF-C4 (3모드 On/missing/Off 정의), raw/official-docs/google-openid-connect-oidc.md#GOIDC-C4 (email claim = email scope 시 제공) |
official-vendor-doc |
Google profile scope 가 first/last name 을 항상 채우는지는 GOIDC 인용 범위 밖 — dev 확인 필요 |
| D4 | email_verified=false 계정의 silent auto-link 차단 — core = D1(AutoLink 미사용) + D2(Confirm Link 소유증명) (이것만으로 성립), trustEmail=false 는 defense-in-depth(위임). 원 결정의 "전용 custom authenticator/mapper hard-reject" 는 현재 구현 artifact가 없어 OUT_OF_BRANCH_SCOPE(hub §5 Deferred) |
core 는 항상 이 결정 — 공격자가 소유 증명 없이는 link 불가(Confirm Link). email_verified=false 를 flow 진입 즉시 hard-reject 하려면 구현·검증된 커스텀 SPI authenticator가 필요 → 별도 variant |
raw/official-docs/keycloak-first-login-flow.md#KC-FLF-C2, raw/official-docs/keycloak-first-broker-login-verify-authenticators-official.md#KC-FBLVERIFY-C4 (+ defense-in-depth 위임 raw/branch-notes/feature-keycloak-idp-brokering-google-client D6) |
official-vendor-doc (core 조합) |
core 차단(D1+D2)은 trustEmail·email_verified 검증과 무관하게 성립 — fix E2E 는 D6 에 blocking 아님. trustEmail=false 값 선택은 owner D6에 공식 근거가 있으나 runtime은 needs-confirmation; 전제 "Google email_verified=false 발급"(Claims To Verify #4)도 부가 방어 강화용으로만 필요 |
구현 가이드
결정(Decisions) 이 "무엇" 이라면 본 §는 "어디에 어떻게" 의 사전 명세 — done-bar(재현→차단 E2E)를 다음 구현자가 되묻지 않고 수행할 수준으로. anchor 는 공식 문서가 규정하는 authenticator 명칭·트리거 조건. 코드 repo(
/home/donghyeon/workspace/keycloak-patterns/)가 아직 없으므로 구현 detail 은planned, admin UI 로만 확인 가능한 값은UNSUPPORTED_IMPL_DECISION. 본 branch owned 구현 대상은 flow 구성(D1~D4) 뿐.trustEmail값·Google client 등록은 raw/branch-notes/feature-keycloak-idp-brokering-google-client 위임, linking key(sub)는 raw/branch-notes/feature-keycloak-account-linking-sub-vs-email 위임 — 본 §는 정책 참조만.
1. 함정 재현 (Reproduce) — email-match auto-linking 계정탈취
Trace: done-bar(hub §8.0 그룹 5) + D1 +
KC-FBLVERIFY-C4/C5+KC-FLF-C2.재현의 정확한 벡터 (2026-07-16 depth-audit Finding 2 반영): AutoLink 는 email/username 값 매칭으로 link 하며
email_verified를 트리거로 보지 않는다(KC-FBLVERIFY-C5). 따라서 재현의 필수 조건은 "공격자 토큰의email_verified=false는 그 email 을 신뢰하면 안 되는 이유(unverified 소유 주장)일 뿐 AutoLink 발동 조건이 아니다.email_verified자동신뢰 벡터는 §2 의trustEmail방어(위임 D6) 관심사로 분리 — 즉 본 재현은email_verified미검증(Claims To Verify #4)에 의존하지 않는다.
- UNSUPPORTED_IMPL_DECISION (재현 harness): 실제 Google 로는 내가 소유하지 않은
victim@example.com토큰을 발급받을 수 없어 real Google 로는before(탈취 성공)관측 불가. 재현은 claim 을 제어 가능한 OIDC OP 로 수행 — (a) 로컬 스택에 2번째 Keycloak realm 을 mock OP 로 세워 main realm 에 외부 OIDC IdP 로 등록하고 그 OP 사용자email=victim@example.com설정, 또는 (b) 경량 mock-oidc OP 로 임의email_verifiedclaim emit. trade-off: (a) Keycloak 자족(추가 realm 운영) vs (b) 경량(별도 컨테이너) — 착수 시 (a) 권장. AutoLink authenticator 의 정확한 UI 명칭("Automatically Set Existing User" vs "Automatically Link Existing Account")·requirement·위치도 admin UI 확정(Claims To Verify #1). 코드 repo 부재 →planned.
| 단계 | 명세 | 근거 |
|---|---|---|
| 전제(dep) | Google IdP 대신 제어 가능한 OIDC OP(2nd Keycloak realm 또는 mock OP)를 main realm 에 외부 IdP 로 등록 — 공격자가 email claim 을 통제해야 함 |
done-bar, depth-audit Finding 1 |
| 피해자 셋업 | main realm 에 local user victim@example.com(password 설정) 존재 |
done-bar |
| 취약 flow | First Broker Login 사본에 AutoLink(Automatically Set Existing User) authenticator 추가 → email 값 매칭으로 무확인 link |
KC-FBLVERIFY-C4 (WARNING), KC-FBLVERIFY-C5 (email/username 매칭) |
| 공격 | 제어 OP 사용자 email=victim@example.com(email_verified=false = 신뢰불가 email 표현이나 AutoLink 트리거 아님) → 그 IdP 로 로그인 → AutoLink 가 email 값으로 victim 계정에 연결 |
KC-FLF-C2 (위협), 목표/WHY 시나리오 |
| 관측(before) | 공격자 세션이 victim 의 계정/roles 보유 — 탈취 성공 로그/스크린샷 | done-bar |
2. 차단 (Fix) — Confirm Link Existing Account
Trace: D1 + D2 +
KC-FLF-C3+KC-FBLVERIFY-C1/C2/C3.
- UNSUPPORTED_IMPL_DECISION: Email vs Re-authentication 중 무엇을 강제할지의 realm-level 선택(SMTP 유무)은 배포 realm 사실 — 본 branch 는 정책(secret 증명 우선 시 email DISABLE)만. trade-off: SMTP 미설정 학습 realm 은 Re-auth 가 자동 폴백이므로 별도 조치 불필요.
| 단계 | 명세 | 근거 |
|---|---|---|
| flow 복원 | AutoLink 제거 → 기본 Handle Existing Account(= Confirm Link Existing Account + Verify Existing Account) 유지 |
D1, KC-FLF-C3 |
| 재인증 관철(선택) | password 소유 증명 강제 시: "Verify Existing Account By Email" DISABLE → "Verify Existing Account By Re-authentication" 실행 | KC-FBLVERIFY-C2, KC-FBLVERIFY-C3 |
| 기본 동작 주의 | SMTP 설정 realm 은 email 확인이 기본(ALTERNATIVE) — secret 미증명이라도 소유 확인은 됨 |
KC-FBLVERIFY-C1 |
| email_verified 보강 (defense-in-depth, 위임) | trustEmail=false 로 IdP email 을 무조건 verified 처리하지 않음. 단 core 차단(Confirm Link 소유증명)은 trustEmail 값과 무관하게 성립 — 본 fix E2E 는 D6 에 blocking 되지 않는 부가 방어 |
위임 raw/branch-notes/feature-keycloak-idp-brokering-google-client D6 (자체 UNSUPPORTED — 근거 확정은 그 branch) |
| 재공격 | 공격자(제어 OP) 로그인 → Confirm Link info page → email 확인/password 재인증 요구 → 소유 증명 실패 → link 차단 | D2, KC-FLF-C3 |
| 관측(after) | before(탈취 성공) vs after(차단) 대조 기록 → locally-verified 승급 근거 |
done-bar |
3. Review Profile 모드 — D3
Trace: D3 +
KC-FLF-C4.
- UNSUPPORTED_IMPL_DECISION: Google
profilescope 가 first/last name 을 항상 채우는지 미확인(Claims To Verify #? — GOIDC 범위 밖). trade-off: 미충족 시missing모드가 안전(누락 시에만 프로필 페이지).
| 모드 | 조건 | 근거 |
|---|---|---|
Off (권장) |
Google 이 email/name 제공 → 프로필 페이지 불필요 | KC-FLF-C4, GOIDC-C4 |
missing |
mandatory(email/first/last name) 미제공 IdP → 누락 시만 표시 | KC-FLF-C4 |
On |
GDPR 등 동의/추가정보 수집 요건 | KC-FLF-C4 |
엣지·실패·의존
R4 캡처용. 정상 경로 외에 구현 중 부딪힐 실패/엣지/다른 계약 의존을 미리 열거.
- 실패·엣지 경로:
- Google-first 가입 lockout (D2): 비밀번호 미설정(Google 으로만 가입) 사용자가 다른 IdP/계정 link 충돌 시 "Verify Existing Account By Re-authentication" 로 넣을 password 가 없어 진행 불가 — email 폴백 또는 대안 경로 설계 필요(
needs-confirmation). - SMTP 미설정 realm (D2): "Verify Existing Account By Email"(기본
ALTERNATIVE) 사용 불가 → 자동으로 "Verify Existing Account By Re-authentication" 폴백(KC-FBLVERIFY-C3). 학습 스택은 SMTP 없이 시작하므로 기본이 Re-auth 임에 유의. - OOTB 충돌감지 = email/username (D1 tension):
Create User If Unique는 IdPsub가 아니라 email/username 으로 충돌 감지(KC-FBLVERIFY-C5). sub-only 매칭·email_verifiedhard-reject 를 원하면 커스텀 SPI authenticator 필요 → 본 branch 범위 밖(§AuditOUT_OF_BRANCH_SCOPE, hub §5 Deferred). - flow 오설정 시 Google IdP 전면 차단: 기본 flow 는 read-only — 반드시 복제 후 편집. 잘못 편집하면 해당 IdP 로그인 전체가 막힘(진행 중 메모).
- 재현용 취약 구성 잔존 위험: 함정 재현(§1) 후 AutoLink authenticator 를 제거하지 않으면 실제 취약점이 남음 — 차단(§2) 단계에서 반드시 원복 확인.
- Google-first 가입 lockout (D2): 비밀번호 미설정(Google 으로만 가입) 사용자가 다른 IdP/계정 link 충돌 시 "Verify Existing Account By Re-authentication" 로 넣을 password 가 없어 진행 불가 — email 폴백 또는 대안 경로 설계 필요(
- 다른 계약 의존:
- raw/branch-notes/feature-keycloak-idp-brokering-google-client
D6(trustEmail=false) +D1~D5(Google client 등록·discovery·redirect URI) — 본 flow 의 전제. IdP 미등록이면 First Broker Login 자체가 트리거되지 않음.trustEmail값이 바뀌면 D4 방어 전제도 변함. - raw/branch-notes/feature-keycloak-account-linking-sub-vs-email
D1(sub 기반 linking key) — 본 flow 는 sub-vs-email 의 linking 정책과 정합해야. 그 branch 는 flow 구성 을 본 branchD1/D2/D4에 위임(역방향 의존). - raw/branch-notes/feature-keycloak-google-claim-attribute-mapping
D3(Sync Mode)/D4(email Attribute Importer) — first-login 시 매핑되는 attribute owner. 매핑이 바뀌면 §Review Profile 입력값도 바뀜. - raw/branch-notes/feature-keycloak-account-linking-spa-ux — Confirm Link info page 노출 시 SPA redirect/return UX. 본 flow 가 확인 페이지를 트리거하면 그 branch 가 UX 를 consume.
- raw/branch-notes/feature-keycloak-idp-brokering-google-client
검증해야 할 주장
공식 문서 근거가 있어도 내 프로젝트/버전에서의 동작을 자동으로 보장하지 않는다.
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
OOTB Default First Broker Login flow 는 auto-link 를 포함하지 않으며(Create User If Unique→Handle Existing Account=Confirm Link 가 기본), 함정 재현엔 Automatically Set Existing User(AutoLink) authenticator 를 명시 추가해야 한다 — 그 정확한 명칭/requirement/추가 위치 |
KC-FBLVERIFY-C4/C5 로 방향은 확정됐으나 배포 버전 admin UI 의 정확한 authenticator 라벨·토글은 미확인 (기존 노트의 "기본이 auto-link" 전제는 §Audit CLAIM_DRIFT 로 정정) |
Keycloak admin console > Authentication > Flows > First Broker Login 복제 후 step 캡처 + AutoLink 추가 시연 | needs-confirmation |
Confirm Link Existing Account 와 Verify Existing Account(By Email / By Re-authentication) 의 requirement 조합이 admin UI 에서 의도대로 설정 가능 |
KC-FLF-C3/KC-FBLVERIFY-C1~C3 는 트리거 조건만; 실제 UI step list·설정 가능성은 별도 |
dev Keycloak flow editor 에서 step list + email authenticator DISABLE 시연 | needs-confirmation |
| Identity Provider 의 "First Login Flow Override" 가 IdP 별로 다른 flow 지정 가능 | 본 branch Sources 에 Override 메커니즘 verbatim 없음(개요만) | Admin console > Identity Providers > Google > Advanced Settings 캡처 또는 admin guide 추가 인용 | needs-confirmation |
Google 이 일부 시나리오에서 email_verified=false ID token 발급 가능 (D4 전제) |
GOIDC-C4 는 email claim 만; email_verified semantics 는 명시적 범위 밖 |
raw/official-docs/google-openid-connect-oidc.md claims table 의 email_verified 행 추가 발췌 또는 dev Google 계정으로 재현 |
needs-confirmation |
email_verified=false hard-reject 를 원하면 커스텀 SPI authenticator 가 필요하다 (D4 OUT_OF_BRANCH_SCOPE 근거) |
OOTB 는 email/username 매칭(KC-FBLVERIFY-C5), email_verified 조건부 거부 built-in 여부 미확인 |
Keycloak Identity Provider Mappers / First Broker Login SPI 문서 확인 + dev 재현 | needs-confirmation |
인용한 authenticator 명칭·기본 등급(ALTERNATIVE)이 배포 예정 Keycloak release tag 에서도 동일 |
근거 raw(first-login-flow.adoc)는 keycloak main branch 기준(KC-FBLVERIFY 버전 caveat) |
배포 버전 tag 의 admin guide / Admin Console 재확인 | needs-confirmation |
Audit & Findings
2026-07-16
/branch-spec채움(기존 corpus 정독 — web 조사 불요, 모든 결정 근거는 이미 raw 에 존재) 결과. 사용자 작성 결정은 verbatim 보존, 아래는 정합 권고·정정만 (CLAUDE.md §11).
- FRAMING_DRIFT (Should-fix, hub 정합): 노트 원 프레이밍 "P1B sub-sub-branch 는 전체
documented-only/ 실 구현 안 함 / wiki 추출 안 함" 은 hub 2026-07-14 재편(§8.0 그룹 5 + §1 성공기준 + §10 Phase 2/3)으로 stale. 현재 이 branch 는 Google 그룹 Tier-2 구현 branch(done-bar = 재현→차단, 목표locally-verified). 헤더·범위·Closure 를 구현 branch 로 갱신, 원 결정문/TODO 는 verbatim 보존. - CLAIM_DRIFT (D1, 정정): 원 전제 "기본 First Broker Login Flow 가
Automatically Link Existing Account를 포함, 이를 제거" 는 부정확. OOTB 기본은Create User If Unique(충돌감지 key = email/usernameKC-FBLVERIFY-C5) →Handle Existing Account(Confirm Link) 이고, email 자동 link 는 별도 opt-inAutomatically Set Existing User(공식 WARNINGKC-FBLVERIFY-C4). done-bar 는 "제거"가 아니라 "재현 위해 추가 → 기본으로 복원"(§구현 가이드 §1→§2). - CORRECTION (D2, 정정): 원 "Verify Existing Account by Re-authentication
REQUIRED(기본)" 은 부정확 — SMTP 설정 realm 은 "Verify Existing Account By Email"(ALTERNATIVE)이 기본(KC-FBLVERIFY-C1). password 재인증 관철엔 admin 이 email authenticator 를 명시 DISABLE 필요(KC-FBLVERIFY-C2); Re-auth 는 email 사용 불가 시 폴백(KC-FBLVERIFY-C3). (동일 정정이 형제 raw/branch-notes/feature-keycloak-account-linking-sub-vs-email §AuditCORRECTION(D2)에도 존재 — 본 branch 가 flow 구성 owner 이므로 정정의 canonical 위치는 여기.) - RESCOPE (D4, UNSUPPORTED → 조합 근거 + OUT_OF_BRANCH_SCOPE): 원 D4 "custom authenticator/mapper 로
email_verified=false강제 차단" 은 그 자체로 근거 부재(UNSUPPORTED_DECISION)였다. 실무 방어는 D1(AutoLink 미사용) + D2(Confirm Link 소유증명) + 위임trustEmail=false(idp-brokering-google-client D6) 의 조합으로 이미 성립(공격자가 소유 증명 없이 link 불가) → 조합 근거로 grounded. flow 진입 즉시 hard-reject 하는 전용 custom SPI authenticator 는 hub §5 Deferred(server-side SPI 트랙) 으로OUT_OF_BRANCH_SCOPE. 전제(Googleemail_verified=false발급)는 Claims To Verify #4. - OUT_OF_BRANCH_SCOPE (이관 권고):
sub기반 충돌감지 전용 authenticator +email_verifiedhard-reject SPI 는 본 branch(flow 구성) 범위 밖 → hub §5 Deferred SPI 트랙 또는 별도 branch(예:feature-keycloak-firstlogin-emailverified-authenticator). 형제 sub-vs-email 도 동일 gap 을 §AuditOUT_OF_BRANCH_SCOPE로 이관 권고 중 — 중복 신설 금지, 단일 SPI branch 로 수렴 권고. - NO_GROUND_TRUTH (한계 명시): 코드 repo
/home/donghyeon/workspace/keycloak-patterns/미생성(hub §9).actually-implemented주장 불가 — 모든 구현 detail 은planned/needs-confirmation. §참조의 ca-tmpl ground truth(registries/error-codes 등)는 본 프로젝트와 무관(keycloak-patterns 는 별도 repo) — 계약값 검증 대상 아님. - BIDIR_LINK (fix 적용): raw/official-docs/keycloak-first-broker-login-verify-authenticators-official 의 Parent 표·
related_branches에 본 branch 가 누락돼 있었음(sub-vs-email 만). 본/branch-spec에서 backlink 추가(양방향 링크 정합,rules/linking-rules). - STALE_SUMMARY 전파 (fix 적용): raw/branch-notes/feature-keycloak-account-linking-spa-ux 가 본 branch D2 를 "Confirm Link + Re-auth
REQUIRED" 로 요약(L116·L181)했으나 KC-FBLVERIFY 정정(Email 기본 / Re-auth 폴백)과 어긋남 → 같은 세션에서 두 참조를 corrected pointer 로 갱신(consistency-contract §전파). - DEPTH_LOOP_1 (2026-07-16 depth-audit 반영, §8c 루프 1회):
branch-depth-auditor가 Blocking 1 + Should-fix 2 를 반환 → 다음 정정: (1) REPRODUCE_HARNESS (Blocking F1) — real Google 로는 미소유 email 토큰 발급 불가로before(탈취)관측 불가 → §구현 가이드 §1 에 제어 가능 OIDC OP(2nd Keycloak realm / mock OP) harness 를UNSUPPORTED_IMPL_DECISION+ trade-off 로 명세. (2) VECTOR_SEPARATION (F2) — AutoLink 는email값 매칭이지email_verified트리거 아님(KC-FBLVERIFY-C5) → §1 에 두 벡터 분리 명시, 재현은 Claims To Verify #4(email_verified 발급)에 비의존. (3) TRUSTEMAIL_DECOUPLE (F3) — 위임 owner raw/branch-notes/feature-keycloak-idp-brokering-google-client D6 의 값 선택 근거가 이후 공식 문서로 보강됐지만, core 차단(D1+D2 Confirm Link)은 여전히trustEmail과 무관하게 성립하고trustEmail=false는 defense-in-depth 다(fix E2E 가 D6 에 blocking 아님). Advisory F4(Review Profile/version hedge)는 이미 정직 헷지 — 조치 불요.
마주친 문제
- 아직 없음(문서 단계 — 코드 repo 생성 시 재현/차단 시연에서 발생 예상).
묶음
- raw/official-docs/google-oidc-discovery-spec
- raw/official-docs/keycloak-first-broker-login-flow
- raw/official-docs/keycloak-first-broker-login-verify-authenticators-official
- raw/official-docs/keycloak-first-login-flow
- raw/official-docs/keycloak-identity-brokering-overview-official
본 sub-sub-branch 는 leaf — 자식 자료 없음. Phase 3 실 구현 또는 외부 산출물 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.
근거 자료
- raw/official-docs/keycloak-first-login-flow — D1/D2/D3 (auto-link 경고 + Confirm Link info page + Review Profile 모드)
- raw/official-docs/keycloak-first-broker-login-verify-authenticators-official — D1/D2 (AutoLink WARNING + Verify authenticators 트리거 조건)
- raw/official-docs/google-openid-connect-oidc — D3/D4 전제 (email scope / email_verified 범위)
- raw/company-tech-blogs/keycloak-google-login-codemancers — D2 corroboration (실무 사례)
- raw/official-docs/keycloak-identity-brokering-overview-official — First Login Flow Override 배경
오류 기록 (이 sub-sub-branch 작업 중 발생)
- (없음 — 현재 문서 단계)
면접 준비 (이 작업에서 나올 수 있는 면접 질문)
- (없음 — 실 구현 단계에 누적) "왜 email auto-linking 이 계정탈취인가 / Confirm Link 가 어떻게 막나 / OOTB 기본 flow 는 이미 안전한가?" 후보.
관련 일일 노트
완료 후 정리
- PR 링크: (없음 — 코드 repo 미생성)
- 리뷰 메모:
- 머지 결과 / 배포 환경: 없음 (현재 문서 단계; done-bar 달성 시
locally-verified=docker compose up로컬 재현→차단) - wiki 추출 대상 (verified만,
wiki/projects/로만 추출): done-bar(재현→차단)locally-verified달성 후 hub §11 정책에 따라 Phase 4 시점 검토. 현재 없음. - 추출하지 않을 항목 (planned / documented-only): 현 시점 전체 (
planned/documented-only).