Files
llm-wiki/vault/10-projects/keycloak-patterns-overview/branch-notes/feature-keycloak-first-broker-login-flow.md
T

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
DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1
WI-KEYCLOAK-PATTERNS-OVERVIEW-015
1 feature-keycloak-first-broker-login-flow
keycloak-patterns
branch
keycloak-patterns
p1b
first-broker-login
account-linking
security
account-takeover
email-verified
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-overviewWI-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=false auto-linking 계정탈취 재현 → Confirm Link Existing Account 로 차단, before/after 기록, 목표 등급 locally-verified. (기존 "documented-only / 실 구현 안 함" 프레이밍은 2026-07-14 재편으로 stale — §Audit FRAMING_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 다(공식 WARNING KC-FBLVERIFY-C4). 따라서 본 branch 의 done-bar 는 "기본에서 auto-link 를 제거"가 아니라 함정을 재현하려면 AutoLink 를 명시 추가한 뒤, 기본 Confirm Link 로 되돌려 차단하는 것이다(§구현 가이드, §Audit CLAIM_DRIFT). 원문은 verbatim 보존.

위험 시나리오 (Auto Link 사용 시):

  1. 공격자가 자신의 Google 계정 email을 victim@example.com으로 위장 (Google이 email_verified=false로 발급)
  2. Keycloak에 이미 victim@example.com으로 가입된 local 계정 존재
  3. Auto Link가 email match만 보고 두 계정을 link → 공격자가 Google 로그인으로 피해자 계정 접근

해결: "Confirm Link Existing Account" flow는 link 전에 사용자가 기존 Keycloak 계정 password를 입력(또는 email 확인)해야 하므로, Google 계정만으로는 link 불가.

  • 이슈: (없음 — 학습 프로젝트)
  • PR: (없음 — 코드 repo /home/donghyeon/workspace/keycloak-patterns/ 아직 미생성, §Audit NO_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=false silent auto-link 차단 (= core D1+D2). raw/branch-notes/feature-keycloak-idp-brokering-google-client D6 (trustEmail=false)는 defense-in-depth로만 consume.
  • 함정 재현 → 차단 E2E 절차 (done-bar): AutoLink 로 계정탈취 재현 → Confirm Link 로 차단, before/after 기록.

제외 범위

의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.

근거 (필수, 최소 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-only
    • Review 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로 사본 생성 후 편집
  • "Automatically Link Existing Account" 단계 제거 또는 DISABLED — 등급: planned
    • 해당 step의 requirement를 DISABLED로 설정
  • "Confirm Link Existing Account" 단계 REQUIRED 활성화 — 등급: planned
    • 사용자에게 기존 계정 link 여부 확인 페이지 표시
    • 이후 Verify Existing Account by Re-authentication step에서 password 입력
  • Identity Provider 설정에서 변경된 flow를 First Login Flow Override로 지정 — 등급: planned
  • Review Profile flow 정책 결정 — 등급: documented-only
    • Google이 email / name / picture 제공 → 신규 사용자 확인 페이지 불필요한 경우 OFF
    • GDPR 등 동의 페이지 필요한 경우 ON
  • email_verified=false silent 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-official KC-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 Account step을 비활성화 (DISABLED). 보안 위험 회피.
  • 2026-05-25: Confirm Link Existing Account + Verify Existing Account by Re-authentication step을 REQUIRED로 활성화. 사용자가 기존 계정 password를 입력해야 link 완료.
  • 2026-05-25: Review Profile flow는 OFF 권장 (Google이 profile 제공). 단, 동의 페이지 비즈니스 요건 있을 시 ON.
  • 2026-05-25 (historical, superseded): Google email_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 Claimsraw/<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=falsedefense-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 = victim 의 email" 이고, 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/email_verified claim 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

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 profile scope 가 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 는 IdP sub 가 아니라 email/username 으로 충돌 감지(KC-FBLVERIFY-C5). sub-only 매칭·email_verified hard-reject 를 원하면 커스텀 SPI authenticator 필요 → 본 branch 범위 밖(§Audit OUT_OF_BRANCH_SCOPE, hub §5 Deferred).
    • flow 오설정 시 Google IdP 전면 차단: 기본 flow 는 read-only — 반드시 복제 후 편집. 잘못 편집하면 해당 IdP 로그인 전체가 막힘(진행 중 메모).
    • 재현용 취약 구성 잔존 위험: 함정 재현(§1) 후 AutoLink authenticator 를 제거하지 않으면 실제 취약점이 남음 — 차단(§2) 단계에서 반드시 원복 확인.
  • 다른 계약 의존:

검증해야 할 주장

공식 문서 근거가 있어도 내 프로젝트/버전에서의 동작을 자동으로 보장하지 않는다.

Claim Why uncertain How to verify Status
OOTB Default First Broker Login flow 는 auto-link 를 포함하지 않으며(Create User If UniqueHandle 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 AccountVerify 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-C4email 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/username KC-FBLVERIFY-C5) → Handle Existing Account(Confirm Link) 이고, email 자동 link 는 별도 opt-in Automatically Set Existing User(공식 WARNING KC-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 §Audit CORRECTION(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. 전제(Google email_verified=false 발급)는 Claims To Verify #4.
  • OUT_OF_BRANCH_SCOPE (이관 권고): sub 기반 충돌감지 전용 authenticator + email_verified hard-reject SPI 는 본 branch(flow 구성) 범위 밖 → hub §5 Deferred SPI 트랙 또는 별도 branch(예: feature-keycloak-firstlogin-emailverified-authenticator). 형제 sub-vs-email 도 동일 gap 을 §Audit OUT_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 생성 시 재현/차단 시연에서 발생 예상).

묶음

본 sub-sub-branch 는 leaf — 자식 자료 없음. Phase 3 실 구현 또는 외부 산출물 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.

근거 자료

오류 기록 (이 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).