Files
llm-wiki/vault/20-evidence/official-docs/keycloak-client-initiated-account-linking.md
T

13 KiB

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
Keycloak Client Initiated Account Linking — Browser-based Account Link API official-doc https://wjw465150.gitbooks.io/keycloak-documentation/content/server_development/topics/identity-brokering/account-linking.html
feature-keycloak-account-linking-spa-ux
keycloak-patterns
official-doc
keycloak-patterns
auth
security
keycloak
2026-07-15

Keycloak Client Initiated Account Linking — Browser-based Account Link API

Layer: raw/official-docs/ — Keycloak Server Development Guide / "Identity Brokering / Client Initiated Account Linking" 섹션 (gitbook 미러 verbatim). raw/official-docs/keycloak-first-login-flow 와 동일 gitbook 미러 출처. feature-keycloak-account-linking-spa-ux D3 (SPA 가 link 를 트리거하는 공식 메커니즘) 의 1차 근거.

Parent / 활용 branch

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-keycloak-account-linking-spa-ux D3 — SPA/client 가 계정 링크를 트리거하는 공식 메커니즘이 "Client Initiated Account Linking"(서명된 redirect URL fabrication + account.manage-account/account.manage-account-links role 요구)이라는 것, 그리고 keycloak-js 에 built-in link login action 이 없다는 것(note 의 Claim #4 keycloak.login({action:'link'}) 가정의 정확성 검증)의 1차 근거

출처 / Source

  • 원본 URL: https://wjw465150.gitbooks.io/keycloak-documentation/content/server_development/topics/identity-brokering/account-linking.html
  • 원본 source: keycloak/keycloak 저장소 docs/documentation/server_development/topics/identity-brokering/account-linking.adoc (fetch 한 HTML 의 data-filepath="server_development/topics/identity-brokering/account-linking.adoc" 속성으로 확인)
  • 아카이브 URL: (미수집)
  • 저자 / 조직: Keycloak (Red Hat). gitbook 미러 재발행자는 W.Stone (<meta name="author" content="W.Stone">) — 원저작자가 아니라 미러 사이트 게시자
  • 발행일: gitbook 미러 페이지의 data-revision="Fri Jun 30 2017 05:56:05 GMT+0000 (UTC)" (Keycloak legacy docs, 정확한 최초 발행일은 gitbook 미러에 별도 명시 없음)
  • 마지막 확인일: 2026-07-15

왜 저장했는지 / Why archived

SPA/client 가 이미 로그인된 사용자 계정에 external IDP(Google 등)를 link 하려 할 때 사용하는 공식 메커니즘의 이름과 정확한 프로토콜(서명된 redirect URL + hash 검증)을 확정하기 위해 저장. feature-keycloak-account-linking-spa-ux 의 TODO 항목 "keycloak.login({ action: 'link', idpHint: 'google' }) 호출로 SPA 에서 link 트리거 가능"이라는 needs-confirmation claim 을 이 공식 문서로 검증(또는 반증)하는 것이 목적.

핵심 인용 / Key quotes (verbatim)

[§Overview, line 6-7] "Keycloak offers a browser-based API that applications can use to link an existing" [...] "user account to a specific external IDP."

[§Preconditions, line 20] "The user must have an account.manage-account or account.manage-account-links role mapping."

[§Preconditions, line 22] "The application must be granted the scope for those roles within its access token"

[§Preconditions, line 24] "The application must have access to its access token as it needs information within it to generate the redirect URL."

[§URL structure, line 28] "{auth-server-root}/auth/realms/{realm}/broker/{provider}/link?client_id={id}&redirect_uri={uri}&nonce={nonce}&hash={hash}"

[§hash param definition, line 53] "This is a Base64 URL encoded hash. This hash is generated by Base64 URL encoding a SHA_256 hash of nonce + token.getSessionState() + token.getIssuedFor() + provider"

[§Why hash is included, line 81] "Why is this hash included? We do this so that the auth server is guaranteed to know that the client application initiated the request and no other rogue app"

[§Post-link behavior, line 85] "After the account has been linked, the auth server will redirect back to the redirect_uri."

[§Refreshing External Tokens, line 97] "If you are using the external token generated by logging into the provider (i.e. a Facebook or Github token), you can refresh this token by re-initiating the account linking API."

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
KC-CIAL-C1 Keycloak 은 "client initiated account linking" 이라는 이름의 browser-based API 를 제공하며, 이는 애플리케이션이 전체 소셜 로그인 옵션을 제공하지 않고도 이미 로그인된 기존 사용자 계정을 특정 external IDP 에 link 할 수 있게 한다 [§Overview, line 6-7] "Keycloak offers a browser-based API that applications can use to link an existing" [...] "user account to a specific external IDP." official-vendor-doc 이미 OIDC 로 로그인된 사용자가 특정 external IDP(예: Google)에 자신의 계정을 link 하려는 시나리오 keycloak-js 같은 client adapter 가 이 API 를 감싸는 built-in 메서드(예: login({action:'link'}))를 제공한다는 것은 아님 — 본 페이지는 서버가 노출하는 redirect-URL 기반 프로토콜만 규정하며 adapter API 표면은 다루지 않음
KC-CIAL-C2 link 프로토콜 시작 전 애플리케이션은 (a) 사용자가 account.manage-account 또는 account.manage-account-links role mapping 을 보유해야 하고, (b) 그 role 에 대한 scope 가 access token 에 부여되어야 하며, (c) redirect URL 생성 정보를 얻기 위해 애플리케이션이 자신의 access token 에 접근할 수 있어야 한다는 3개 전제조건을 명시 [§Preconditions, line 20] "The user must have an account.manage-account or account.manage-account-links role mapping." + [§Preconditions, line 22] "The application must be granted the scope for those roles within its access token" + [§Preconditions, line 24] "The application must have access to its access token as it needs information within it to generate the redirect URL." official-vendor-doc client-initiated account linking 프로토콜을 시작하려는 모든 OIDC client (SPA 포함) 이 role mapping 이 Keycloak 기본 realm/client 설정에 자동 포함되는지, 즉 admin 이 별도로 사용자에게 account.manage-account-links role 을 assign 해야 하는지는 본 인용 범위 밖 — role 요건 존재만 명시, 부여 절차는 admin guide 별도 참조 필요
KC-CIAL-C3 link 를 시작하는 redirect URL 은 애플리케이션이 직접 fabricate 해야 하며, 정확한 템플릿은 {auth-server-root}/auth/realms/{realm}/broker/{provider}/link?client_id={id}&redirect_uri={uri}&nonce={nonce}&hash={hash} 이다 [§URL structure, line 28] "{auth-server-root}/auth/realms/{realm}/broker/{provider}/link?client_id={id}&redirect_uri={uri}&nonce={nonce}&hash={hash}" official-vendor-doc client-initiated account linking 시작 시 애플리케이션이 구성해야 하는 redirect URL 형식 이 URL 을 애플리케이션 코드에서 어떤 라이브러리/헬퍼로 만들어야 하는지는 규정하지 않음 — 문서의 예시 코드는 Java Servlet 전용이며, keycloak-js 같은 JS adapter 가 이 URL 구성을 자동화하는 헬퍼를 제공하는지는 본 페이지 범위 밖
KC-CIAL-C4 hash 파라미터는 nonce + token.getSessionState() + token.getIssuedFor() + provider 문자열의 SHA_256 다이제스트를 Base64-URL 인코딩한 값이며, 이 hash 를 포함하는 이유는 auth server 가 client application 이 요청을 시작했음을 보장하기 위함(rogue app 의 임의 link 요청 방지)이다 [§hash param definition, line 53] "This is a Base64 URL encoded hash. This hash is generated by Base64 URL encoding a SHA_256 hash of nonce + token.getSessionState() + token.getIssuedFor() + provider" + [§Why hash is included, line 81] "Why is this hash included? We do this so that the auth server is guaranteed to know that the client application initiated the request and no other rogue app" official-vendor-doc hash 파라미터 계산 메커니즘과 그 보안 목적(anti-spoofing) 이해 "이 API 가 CSRF 공격을 완전히 막는다"는 뜻은 아님 — 문서 자체가 Warning 블록에서 "does not completely prevent CSRF attacks for this operation" 이라 명시하며 애플리케이션이 별도 CSRF 방어 책임을 진다고 경고
KC-CIAL-C5 link 성공 후 auth server 는 redirect_uri 로 리다이렉트하며, 외부 provider 로부터 얻은 external token(예: Facebook/Github token)은 account linking API 를 재호출(re-initiate)하여 refresh 할 수 있다 [§Post-link behavior, line 85] "After the account has been linked, the auth server will redirect back to the redirect_uri." + [§Refreshing External Tokens, line 97] "If you are using the external token generated by logging into the provider (i.e. a Facebook or Github token), you can refresh this token by re-initiating the account linking API." official-vendor-doc link 완료 후 애플리케이션 콜백 처리, 그리고 external token 수명 관리(refresh) 이 refresh 가 자동/백그라운드로 일어난다는 뜻이 아님 — 애플리케이션이 명시적으로 account linking API(즉 동일한 redirect URL fabrication 절차)를 다시 트리거해야 하는 수동 재시작 메커니즘

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • KC-CIAL-C1: "Client Initiated Account Linking" 이 SPA/client 가 계정 링크를 트리거하는 공식 메커니즘의 이름이라는 사실
    • KC-CIAL-C2: link 트리거 전제조건 3가지 (role mapping + scope + access token 접근권)
    • KC-CIAL-C3: 서명된 redirect URL 의 정확한 템플릿
    • KC-CIAL-C4: hash 계산 공식과 그 anti-spoofing 목적
    • KC-CIAL-C5: post-link redirect 동작과 external token refresh 방법
  • 이 자료가 증명하지 않는 것:
    • Keycloak Account REST API 의 linked-accounts read endpoint(GET /realms/{realm}/account/linked-accounts) 존재나 동작 — 본 페이지는 이 endpoint 를 전혀 언급하지 않음. feature-keycloak-account-linking-spa-ux 의 "SPA가 link 상태를 표시하는 방법" 관련 결정은 본 자료로 뒷받침되지 않음(별도 raw 필요)
    • keycloak.login({ action: 'link' }) 같은 keycloak-js adapter built-in 메서드의 존재 — 본 페이지는 서버가 노출하는 raw HTTP 프로토콜(redirect URL fabrication)만 규정하며, 어떤 JS adapter 메서드가 이를 감싸는지는 전혀 언급하지 않는다. 즉 feature-keycloak-account-linking-spa-ux note 의 keycloak.login({action:'link', idpHint:'google'}) 가정은 이 공식 문서로 확인되지 않음 — 이 API 는 본 페이지가 기술하는 raw redirect-URL 구성(hash 서명 포함)을 애플리케이션이 직접 수행해야 함을 시사하며, adapter 가 이를 1-call 로 감싸준다는 근거는 없음
    • 예시 코드가 Java Servlet 전용이므로, 브라우저 JS(SPA) 환경에서 token.getSessionState() 같은 값을 SPA 가 직접 어떻게 얻는지(keycloak-js 의 tokenParsed 필드 사용 여부 등)는 본 페이지 범위 밖
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • Keycloak Account REST API 의 linked-accounts endpoint 공식 문서 별도 수집 (SPA 가 link 상태를 표시하는 방법의 근거)
    • keycloak-js adapter 공식 API 레퍼런스에서 login() 메서드의 action 파라미터 지원 여부 확인 (현재 버전 기준)
    • dev 환경에서 SPA 가 직접 이 redirect URL 을 fabricate 하고 hash 를 계산해 link 를 트리거할 수 있는지 실 검증

메모 / Notes

  • 이 문서는 feature-keycloak-account-linking-spa-uxneeds-confirmation claim("keycloak.login({ action: 'link', idpHint: 'google' }) 호출로 SPA 에서 link 트리거 가능")을 직접 지지하지 않는다 — 오히려 이 페이지가 기술하는 프로토콜은 애플리케이션이 redirect URL 을 수동으로 구성(hash 서명 포함)해야 함을 보여주므로, adapter 의 1-call built-in 존재 가정에 반하는 정황 증거에 가깝다. 다만 이 페이지 자체가 adapter API 를 다루지 않으므로 "keycloak-js 에 그런 메서드가 없다"를 확정하려면 keycloak-js 공식 adapter 문서를 별도 수집해야 한다(needs-confirmation 유지, 반증 아님 — 부재 증명은 안 됨).
  • Account REST API linked-accounts endpoint 는 완전히 별도 raw 수집 대상.