HTMLTAG_67__HTMLTAG_68___1。客戶政策___HTMLTAG_69__HTMLTAG_70
客戶端策略是一個框架,允許在客戶端上自動強制執行安全性要求。您無需手動檢查每個用戶端的配置,只需定義策略,以便 Keycloak 自動驗證和強制執行。
___HTMLTAG_75__HTMLTAG_76___1.1 為什麼我們需要客戶政策? HTMLTAG_77__HTMLTAG_78
-
___HTMLTAG_80__HTMLTAG_81__HTMLTAG_82___一致性:確保所有客戶端遵守相同的安全標準____HTMLTAG_84__HTMLTAG_85___
___HTMLTAG_86__HTMLTAG_87__HTMLTAG_88___自動化:自動拒絕不合規請求___HTMLTAG_90__HTMLTAG_91___
___HTMLTAG_92__HTMLTAG_93__HTMLTAG_94___合規:執行業界標準(FAPI、PSD2、開放銀行)___HTMLTAG_96__HTMLTAG_97___
___HTMLTAG_98__HTMLTAG_99__HTMLTAG_100___治理:控制客戶端註冊與設定___HTMLTAG_102__HTMLTAG_103___
HTMLTAG_105__HTMLTAG_106___1.2 架構:設定檔、條件、執行器___HTMLTAG_107__HTMLTAG_108
客戶端策略包含 3 個主要元件:
預編碼_0
___HTMLTAG_113__HTMLTAG_114___元素____HTMLTAG_115__HTMLTAG_116___說明____HTMLTAG_117__HTMLTAG_118___範例____HTMLTAG_119__HTMLTAG_120___ ___HTMLTAG_123__HTMLTAG_124__HTMLTAG_125___設定檔___HTMLTAG_126__HTMLTAG_127__HTMLTAG_128___執行器集 —定義「執行什麼「___HTMLTAG_129__HTMLTAG_130__HTMLTAG_131___fapi-2-安全設定檔___HTMLTAG_132__HTMLTAG_133__HTMLTAG_134___ ___HTMLTAG_135__HTMLTAG_136__HTMLTAG_137___條件___HTMLTAG_138__HTMLTAG_139__HTMLTAG_140___條件決定哪些客戶端受到影響 - 「為誰強制執行」___HTMLTAG_141__HTMLTAG_142___客戶端具有該角色fapi-客戶端___HTMLTAG_144__HTMLTAG_145__HTMLTAG_146___
___HTMLTAG_147__HTMLTAG_148__HTMLTAG_149___執行器___HTMLTAG_150__HTMLTAG_151__HTMLTAG_152____具體執行邏輯 —「如何執行」____HTMLTAG_153__HTMLTAG_154____MLTAGML
HTMLTAG_159__HTMLTAG_160___1.3 建立客戶資料___HTMLTAG_161__HTMLTAG_162
___HTMLTAG_164__HTMLTAG_165___轉至 領域設定 → 客戶端策略 → 選項卡 MLTAG_170___1HTHTML
___HTMLTAG_174__HTMLTAG_175___點選 建立客戶資料___HTMLTAG_177__HTMLTAG_178__HTMLTAG_179___
___HTMLTAG_180__HTMLTAG_181___输入 名称 和 说明___HTMLTAG_185__HTMLTAG_186__HTMLTAG_187___
___HTMLTAG_188__HTMLTAG_189___點選 儲存 → 開啟設定檔 → 點選 新增執行者___HTMLTAG_193__HTMLTAG_194__5MLG_新增執行者___HTMLTAG_193__HTMLTAG_194__5MLG_194__19
HTMLTAG_197__HTMLTAG_198___1.4 可用的執行器___HTMLTAG_199__HTMLTAG_200
___HTMLTAG_203__HTMLTAG_204___執行器___HTMLTAG_205__HTMLTAG_206___說明____HTMLTAG_207__HTMLTAG_208___參數____HTMLTAG_209__HTMLTAG_210___
___HTMLTAG_213__HTMLTAG_214__HTMLTAG_215___安全客戶端身份驗證器____HTMLTAG_216__HTMLTAG_217__HTMLTAG_218___需要特定驗證方法____HTMLTAG_219__HTMLTAG_220___允許的驗證器:client-secret、client-jwt、客戶端-x509___HTMLTAG_221__HTMLTAG_222___
___HTMLTAG_223__HTMLTAG_224__HTMLTAG_225___PKCE 強制器___HTMLTAG_226__HTMLTAG_227__HTMLTAG_228___必需的PKCE____HTMLTAG_229__HTMLTAG_230___增強:開啟(如果客戶端缺失,則自動新增)___HTMLTAG_231__HTMLTAG_232___
___HTMLTAG_233__HTMLTAG_234__HTMLTAG_235___安全簽章演算法____HTMLTAG_236__HTMLTAG_237__HTMLTAG_23 8___僅允許安全演算法__HTMLTAG_239__HTMLTAG_240___預設:RS256、ES256、PS256___HTMLTAG_241__HTMLTAG_242___
___HTMLTAG_243__HTMLTAG_244__HTMLTAG_245___簽章 JWT 的安全簽章演算法___HTMLTAG_246__HTMLTAG_247__HTMLTAG_248___客戶端 JWT驗證演算法____HTMLTAG_249__HTMLTAG_250___PS256、ES256(不允許RS256)___HTMLTAG_251__HTMLTAG_252___
___HTMLTAG_253__HTMLTAG_254__HTMLTAG_255___密鑰執行器持有者____HTMLTAG_256__HTMLTAG_257__HTMLTAG_258___所需的令牌綁定(mTLS 或DPoP)____HTMLTAG_259__HTMLTAG_260___自動設定:ON___HTMLTAG_261__HTMLTAG_262___
___HTMLTAG_263__HTMLTAG_264__HTMLTAG_265___DPoP 證明驗證器___HTMLTAG_266__HTMLTAG_267__HTMLTAG_268___令牌請求中所需的 DPoP 證明___HTMLTAG_269__HTMLTAG_707012720_____
___HTMLTAG_273__HTMLTAG_274__HTMLTAG_275___機密用戶端執行者___HTMLTAG_276__HTMLTAG_277__HTMLTAG_278___僅機密客戶端___HTMLTAG_279__HTMLTAG_280__HTTAG_280__HT
___HTMLTAG_283__HTMLTAG_284__HTMLTAG_285___需同意___HTMLTAG_286__HTMLTAG_287__HTMLTAG_288___需要同意畫面_______HTMLTAG_290HTMLTAU_2911__
___HTMLTAG_293__HTMLTAG_294__HTMLTAG_295___停用全範圍___HTMLTAG_296__HTMLTAG_297__HTMLTAG_298___停用全範圍映射____HTMLTAG_299__HTMLTAG_300__HTMLTAG_30110299__
___HTMLTAG_303__HTMLTAG_304__HTMLTAG_305___拒絕隱式授權___HTMLTAG_306__HTMLTAG_307__HTMLTAG_308___禁止隱式流___HTMLTAG_309__HTMLTAG_310__HTMLTAG_311112G1310__HT
___HTMLTAG_313__HTMLTAG_314__HTMLTAG_315___拒絕資源所有者密碼憑證授予___HTMLTAG_316__HTMLTAG_317__HTMLTAG_318___不允許 ROPC___HTMLTAG_319__HTMLTAG_320MLTAGML_32010GML
___HTMLTAG_323__HTMLTAG_324__HTMLTAG_325___安全重定向 URI 強制器___HTMLTAG_326__HTMLTAG_327__HTMLTAG_328___驗證重定向 URI____HTMLTAG_329__HTMLTAGMLTAG_328___驗證重新導向 URI____HTMLTAG_329__HTMLTAGML_330___/TMLTAGML”
___HTMLTAG_333__HTMLTAG_334__HTMLTAG_335___安全請求物件___HTMLTAG_336__HTMLTAG_337__HTMLTAG_338___所需的 JAR(JWT 安全授權請求)___HTMLTAG_339__HTMLTAG_34014401
___HTMLTAG_343__HTMLTAG_344__HTMLTAG_345___安全回應類型___HTMLTAG_346__HTMLTAG_347__HTMLTAG_348___C請允許安全回應類型___HTMLTAG_349__HTMLTAG_350___允許:代碼(無令牌,id_token)___HTMLTAG_351__HTMLTAG_352___
___HTMLTAG_353__HTMLTAG_354__HTMLTAG_355___安全會話強制器____HTMLTAG_356__HTMLTAG_357__HTMLTAG_358___強制會話設定____HTMLTAG_359__HTMLTAG_360__1TAG_360__132G_360__
___HTMLTAG_365__HTMLTAG_366___1.5 可用條件__HTMLTAG_367__HTMLTAG_368___
___HTMLTAG_371__HTMLTAG_372___條件____HTMLTAG_373__HTMLTAG_374___說明____HTMLTAG_375__HTMLTAG_376___範例____HTMLTAG_377__HTMLTAG_378___
___HTMLTAG_381__HTMLTAG_382__HTMLTAG_383___任何客戶端___HTMLTAG_384__HTMLTAG_385__HTMLTAG_386___適用於所有客戶端___HTMLTAG_387__HTMLTAG_388886___適用於所有客戶端___HTMLTAG_387__HTMLTAG_3888886___
___HTMLTAG_391__HTMLTAG_392__HTMLTAG_393___客戶端存取類型___HTMLTAG_394__HTMLTAG_395__HTMLTAG_396___基於客戶端類型(公開/機密)___HTMLTAG_397__HTMLTAG_398___MLTAG_398___ PKCE___HTMLTAG_399__HTMLTAG_400___
___HTMLTAG_401__HTMLTAG_402__HTMLTAG_403___客戶端角色___HTMLTAG_404__HTMLTAG_405__HTMLTAG_406___客戶端具有特定角色_ ___HTMLTAG_407__HTMLTAG_408___客戶端具有fapi相容___HTMLTAG_410__HTMLTAG_411__HTMLTAG_412___
___HTMLTAG_413__HTMLTAG_414__HTMLTAG_415___客戶端範圍____HTMLTAG_416__HTMLTAG_417__HTMLTAG_418___客戶端使用特定範圍____HTMLTAG_419__HTMLTAG_420____客戶端請求範圍付款___HTMLTAG_422__HTMLTAG_423__HTMLTAG_424___
___HTMLTAG_425__HTMLTAG_426__HTMLTAG_427___客戶端更新來源群組___HTMLTAG_428__HTMLTAG_429__HTMLTAG_430___基於來源建立/更新客戶端___HTMLTAG_431__HTMLTAG_432___基於來源建立/更新客戶端___HTMLTAG_431__HTMLTAG_432___透過動態註冊/更新客戶端4___3_U431__
___HTMLTAG_435__HTMLTAG_436__HTMLTAG_437___客戶端更新上下文___HTMLTAG_438__HTMLTAG_439__HTMLTAG_440___客戶端更新時的上下文___HTMLTAG_441__HTMLTAG_4440___客戶端更新時的上下文___HTMLTAG_441__HTMLTAG_442________24ML4146
HTMLTAG_447__HTMLTAG_448___1.6 建立客戶端策略___HTMLTAG_449__HTMLTAG_450
___HTMLTAG_452__HTMLTAG_453___轉至 領域設定 → 客戶端策略 → 選項卡 策略 → 選項卡 策略___MLTAGML
___HTMLTAG_462__HTMLTAG_463___點選 建立客戶政策___HTMLTAG_465__HTMLTAG_466__HTMLTAG_467___
___HTMLTAG_468__HTMLTAG_469___输入 名称 和 说明___HTMLTAG_473__HTMLTAG_474__HTMLTAG_475___
___HTMLTAG_476__HTMLTAG_477___新增 條件(決定哪些客戶端受到影響)___HTMLTAG_480__HTMLTAG_481___
___HTMLTAG_482__HTMLTAG_483___新增 客戶設定檔(適用哪個設定檔)___HTMLTAG_486__HTMLTAG_487___
預編碼_1
HTMLTAG_489__HTMLTAG_490___1.7 實際政策範例___HTMLTAG_491__HTMLTAG_492
HTMLTAG_493__HTMLTAG_494___政策 1:所有客戶端的基本安全性___HTMLTAG_495__HTMLTAG_496
預編碼_2
HTMLTAG_497__HTMLTAG_498___政策 2:金融 API 的高安全性____HTMLTAG_499__HTMLTAG_500
預編碼_3
HTMLTAG_501__HTMLTAG_502___2。 FAPI 2.0 安全設定檔___HTMLTAG_503__HTMLTAG_504
FAPI(金融級 API)是 OpenID 基金會開發的一套高安全標準,廣泛應用於 開放銀行、支付服務指令 2 (PSD2) 和金融應用程式。
HTMLTAG_511__HTMLTAG_512___2.1 FAPI 2.0 基準設定檔___HTMLTAG_513__HTMLTAG_514
Keycloak 為 FAPI 2.0 提供內建設定檔:
___HTMLTAG_519__HTMLTAG_520___請求___HTMLTAG_521__HTMLTAG_522___說明___HTMLTAG_523__HTMLTAG_524___
___HTMLTAG_527__HTMLTAG_528___僅限授權程式碼流___HTMLTAG_529__HTMLTAG_530___不允許隱式,ROPC____HTMLTAG_531__HTMLTAG_532___
___HTMLTAG_533__HTMLTAG_534___PKCE (S256)___HTMLTAG_535__HTMLTAG_536___所有客戶端必需____HTMLTAG_537__HTMLTAG_538___
___HTMLTAG_539__HTMLTAG_540___機密客戶端___HTMLTAG_541__HTMLTAG_542___所需的客戶端驗證___HTMLTAG_543__HTMLTAG_544___
___HTMLTAG_545__HTMLTAG_546___安全簽章演算法____HTMLTAG_547__HTMLTAG_548___PS256、ES256(無 RS256)___HTMLTAG_549__HTMLTAG_550___
___HTMLTAG_551__HTMLTAG_552___寄件者限制令牌___HTMLTAG_553__HTMLTAG_554___DPoP 或 mTLS 令牌綁定___HTMLTAG_555__HTMLTAG_556___
___HTMLTAG_557__HTMLTAG_558___重定向 URI 完全匹配____HTMLTAG_559__HTMLTAG_560___無通配符____HTMLTAG_561__HTMLTAG_562___
___HTMLTAG_563__HTMLTAG_564___需要 HTTPS___HTMLTAG_565__HTMLTAG_566___對於所有端點____HTMLTAG_567__HTMLTAG_568___
___HTMLTAG_571__HTMLTAG_572___2.2 FAPI 2.0 高階設定檔(訊息簽章)HTMLTAG_573__HTMLTAG_574
除了基線之外,高階設定檔新增:
___HTMLTAG_578__HTMLTAG_579__HTMLTAG_580___PAR(推送授權請求) — RFC 9126:在重定向之前透過反向通道傳送授權請求____HTMLTAG_582__HTMLTAG_583___
___HTMLTAG_584__HTMLTAG_585__HTMLTAG_586___JAR(JWT 安全授權請求) — RFC 9101:以 JWT 簽署的授權參數____HTMLTAG_588__HTMLTAG_589___
___HTMLTAG_590__HTMLTAG_591__HTMLTAG_592___JARM(JWT 安全授權回應模式):以 JWT 簽署的授權回應____HTMLTAG_594__HTMLTAG_595___
預編碼_4______HTMLTAG_597__HTMLTAG_598___2.3 在 Keycloak 中啟用 FAPI 2.0___HTMLTAG_599__HTMLTAG_600
___HTMLTAG_602__HTMLTAG_603___轉至 領域設定 → 客戶端策略 → 選項卡 MLTAG_608___1HTHTMLTA4101014U41TAG_608___
___HTMLTAG_612__HTMLTAG_613___Keycloak 可用 全域設定檔:
___HTMLTAG_618__HTMLTAG_619___fapi-2-安全設定檔___HTMLTAG_620__HTMLTAG_621___
___HTMLTAG_622__HTMLTAG_623___fapi-2-訊息簽署設定檔___HTMLTAG_624__HTMLTAG_625___
___HTMLTAG_628__HTMLTAG_629___使用對應的設定檔建立策略___HTMLTAG_630__HTMLTAG_631___
___HTMLTAG_632__HTMLTAG_633___分配條件以選擇需要合規性的客戶___HTMLTAG_634__HTMLTAG_635___
預編碼_5
HTMLTAG_637__HTMLTAG_638___3。客戶端秘密輪換___HTMLTAG_639__HTMLTAG_640
客戶端金鑰輪換允許更改客戶端金鑰 不會導致停機 — 舊金鑰在過渡期間保持活動狀態。
HTMLTAG_645__HTMLTAG_646___3.1 設定客戶端秘密輪調___HTMLTAG_647__HTMLTAG_648
與執行程式一起使用 客戶端策略 秘密輪替:
預編碼_6
___HTMLTAG_655__HTMLTAG_656___運作原理:HTMLTAG_657__HTMLTAG_658
預編碼_7
HTMLTAG_659__HTMLTAG_660___3.2 實作秘密輪調___HTMLTAG_661__HTMLTAG_662
預編碼_8
4.服務帳戶___HTMLTAG_665__HTMLTAG_666___
當為機密客戶端啟用 服務帳戶角色 時,Keycloak 會為該客戶端建立一個特殊的 服務帳戶使用者。此使用者代表機器對機器操作中的客戶端。
HTMLTAG_673__HTMLTAG_674___4.1 服務帳號使用者___HTMLTAG_675__HTMLTAG_676
預編碼_9
HTMLTAG_677__HTMLTAG_678___4.2 將角色指派給服務帳戶___HTMLTAG_679__HTMLTAG_680
___HTMLTAG_682__HTMLTAG_683___開啟客戶端 → 選項卡 服務帳戶角色___HTMLTAG_685__HTMLTAG_686__HTMLTAG_687___
___HTMLTAG_688__HTMLTAG_689___點選 指派角色___HTMLTAG_691__HTMLTAG_692__HTMLTAG_693___
___HTMLTAG_694__HTMLTAG_695___選擇領域角色或依客戶端過濾以指派客戶端角色___HTMLTAG_696__HTMLTAG_697___
預編碼_10______HTMLTAG_699__HTMLTAG_700___4.3 服務帳戶最佳實務___HTMLTAG_701__HTMLTAG_702
___HTMLTAG_704__HTMLTAG_705__HTMLTAG_706___最低權限:僅向每個服務分配必要的角色___HTMLTAG_708__HTMLTAG_709___
___HTMLTAG_710__HTMLTAG_711__HTMLTAG_712___單獨的客戶端:為每個微服務建立單獨的客戶端,不共用___HTMLTAG_714__HTMLTAG_715___
___HTMLTAG_716__HTMLTAG_717__HTMLTAG_718___審核:啟用事件日誌記錄以追蹤服務帳戶活動____HTMLTAG_720__HTMLTAG_721___
___HTMLTAG_722__HTMLTAG_723__HTMLTAG_724___令牌生命週期短:服務帳戶的存取權杖應該很短(1-5 分鐘)___HTMLTAG_726__HTMLTAG_727___
___HTMLTAG_728__HTMLTAG_729__HTMLTAG_730___輪換憑證:使用客戶端金鑰輪替或基於憑證的驗證___HTMLTAG_732__HTMLTAG_733___
HTMLTAG_735__HTMLTAG_736___5。受眾支持___HTMLTAG_737__HTMLTAG_738
受眾(aud 宣告)決定要使用哪個 資源伺服器 存取權杖。這是防止令牌被用於不需要的服務的重要安全機制。
HTMLTAG_745__HTMLTAG_746___5.1 問題___HTMLTAG_747__HTMLTAG_748
# Mặc định, access token chỉ có aud = client-id đã request
{
"aud": "my-frontend-app", // ← chỉ có client đã request
"azp": "my-frontend-app"
}
# Resource Server (my-api-service) verify token:
# → aud không chứa "my-api-service"
# → REJECT! (nếu resource server validate audience)
HTMLTAG_749__HTMLTAG_750___5.2 解決方案:受眾協定映射器___HTMLTAG_751__HTMLTAG_752
將 受眾映射器 新增至客戶端或客戶端範圍,以將資源伺服器新增至 aud:
# Cách 1: Thêm Audience Mapper trực tiếp vào client
Client: my-frontend-app → Client scopes → Dedicated scope → Add mapper
Mapper Type: Audience
Name: api-audience
Included Client Audience: my-api-service
Included Custom Audience: (trống)
Add to ID token: OFF
Add to access token: ON
# Cách 2: Tạo Client Scope chứa Audience Mapper
Client Scope: api-access
Mapper: Audience → my-api-service
Gán scope cho frontend client
# Kết quả trong access token:
{
"aud": ["my-frontend-app", "my-api-service"],
"azp": "my-frontend-app"
}
HTMLTAG_759__HTMLTAG_760___5.3 受眾解析映射器___HTMLTAG_761__HTMLTAG_762
Keycloak 具有內建 Audience Resolve 映射器(在預設範圍 roles) — 自動為使用者擁有客戶端的用戶端新增用戶端的用戶端新增用戶aud角色:
# Nếu user có role "app-admin" của client "my-api-service"
# → Audience Resolve tự động thêm "my-api-service" vào aud
{
"aud": ["my-frontend-app", "my-api-service"],
"resource_access": {
"my-api-service": {
"roles": ["app-admin"]
}
}
}
HTMLTAG_771__HTMLTAG_772___6。機密客戶憑證___HTMLTAG_773__HTMLTAG_774
HTMLTAG_775__HTMLTAG_776___6.1 客戶端 ID 與秘密___HTMLTAG_777__HTMLTAG_778
最簡單的方法 — 用戶端在請求中傳送 ID 和金鑰:
# Cách 1: Form parameter
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id=my-client&
client_secret=my-secret
# Cách 2: HTTP Basic Authentication
POST /token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=client_credentials
___HTMLTAG_781__HTMLTAG_782___6.2 簽章 JWT (private_key_jwt)HTMLTAG_783__HTMLTAG_784
客戶端建立並使用私鑰簽署 JWT,傳送至 Keycloak。 Keycloak 使用註冊的公鑰/憑證進行驗證。
___HTMLTAG_787__HTMLTAG_788___Keycloak中的設定:HTMLTAG_789__HTMLTAG_790
___HTMLTAG_792__HTMLTAG_793___客戶端 → 選項卡 憑證 → 客戶端身份驗證器: JWT___HTMLTAG_799__HTMLTAG_800__HTMLTAG_801___
___HTMLTAG_802__HTMLTAG_803___上傳客戶端憑證或 JWKS URL___HTMLTAG_804__HTMLTAG_805___
# Tạo key pair cho client
openssl genrsa -out client-private.pem 2048
openssl req -new -x509 -key client-private.pem -out client-cert.pem -days 365
# Upload client-cert.pem vào Keycloak client Credentials tab
# Token request với client_assertion
POST /realms/my-realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id=my-client&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiIs...
___HTMLTAG_807__HTMLTAG_808___客戶端斷言 JWT 結構:HTMLTAG_809__HTMLTAG_810
{
"iss": "my-client", // Client ID
"sub": "my-client", // Client ID
"aud": "http://localhost:8080/realms/my-realm", // Token endpoint
"iat": 1711800000,
"exp": 1711800060, // Short-lived (60s)
"jti": "unique-jwt-id" // Unique ID
}
___HTMLTAG_811__HTMLTAG_812___6.3 X.509 憑證/相互 TLS___HTMLTAG_813__HTMLTAG_814___
客戶端使用客戶端 TLS 憑證(相互 TLS — mTLS)進行驗證。這是最安全的方法。
___HTMLTAG_817__HTMLTAG_818___設定:HTMLTAG_819__HTMLTAG_820
___HTMLTAG_822__HTMLTAG_823___客戶端 → 選項卡 憑證 → 客戶端驗證器:X.50憑證___HTMLTAG_829__HTMLTAG_830__HTMLTAG_831___
___HTMLTAG_832__HTMLTAG_833___輸入 主題 DN 或憑證匹配模式___HTMLTAG_836__HTMLTAG_837___
___HTMLTAG_838__HTMLTAG_839___設定Keycloak伺服器啟用mTLS端點___HTMLTAG_840__HTMLTAG_841___
# Keycloak mTLS configuration (quarkus)
# conf/keycloak.conf hoặc environment variables
KC_HTTPS_CLIENT_AUTH=request
KC_HTTPS_KEY_STORE_FILE=/opt/keycloak/certs/server-keystore.p12
KC_HTTPS_TRUST_STORE_FILE=/opt/keycloak/certs/truststore.p12
# Client gọi token endpoint với client certificate
curl -s -X POST \
"https://localhost:8443/realms/my-realm/protocol/openid-connect/token" \
--cert client-cert.pem \
--key client-private.pem \
-d "grant_type=client_credentials" \
-d "client_id=my-mtls-client"
___HTMLTAG_843__HTMLTAG_844___將 mTLS 與憑證綁定令牌結合:HTMLTAG_845__HTMLTAG_846
# Access token chứa certificate thumbprint
{
"cnf": {
"x5t#S256": "sha256-thumbprint-of-client-certificate"
}
}
# Resource server verify:
# 1. Client gửi request với TLS client certificate
# 2. Resource server extract certificate thumbprint
# 3. So sánh với cnf.x5t#S256 trong access token
# → Nếu match → token hợp lệ + bound to correct client
___HTMLTAG_847__HTMLTAG_848___7。標準代幣交換 (RFC 8693)HTMLTAG_849__HTMLTAG_850
令牌交換允許服務 交換權杖接收具有不同權限或受眾的新代幣。
HTMLTAG_855__HTMLTAG_856___7.1 使用案例___HTMLTAG_857__HTMLTAG_858
___HTMLTAG_860__HTMLTAG_861__HTMLTAG_862___委託:服務 A 希望「代表」使用者呼叫服務 B — 與受眾交換存取權杖以取得新代幣 = 服務 B___HTMLTAG_864__HTMLTAG_865___
___HTMLTAG_866__HTMLTAG_867__HTMLTAG_868___模擬:管理員想要扮演另一個使用者___HTMLTAG_870__HTMLTAG_871___
___HTMLTAG_872__HTMLTAG_873__HTMLTAG_874___令牌類型轉換:交換 SAML 斷言的存取權杖(反之亦然)___HTMLTAG_876__HTMLTAG_877___
HTMLTAG_879__HTMLTAG_880___7.2 令牌交換配置___HTMLTAG_881__HTMLTAG_882
Keycloak 中的令牌交換是 預覽功能 — 需要啟用:
# Bật feature
bin/kc.sh start-dev --features=token-exchange
# Docker
docker run -e KC_FEATURES=token-exchange quay.io/keycloak/keycloak:26.2.4 start-dev
___HTMLTAG_887__HTMLTAG_888___設定權限:HTMLTAG_889__HTMLTAG_890
___HTMLTAG_892__HTMLTAG_893___開啟 目標客戶端(您想要交換權杖的客戶端)→ 標籤 __HTHTMLTAG_897__HTMLTAG_898
___HTMLTAG_900__HTMLTAG_901___已啟用 已啟用權限___HTMLTAG_903__HTMLTAG_904__HTMLTAG_905___
___HTMLTAG_906__HTMLTAG_907___點選 令牌交換 權限 → 設定策略以允許來源客戶端交換___HTMLTAG_910__HTMLTAG_911___
預編碼_20______HTMLTAG_913__HTMLTAG_914___7.3 委託與模擬___HTMLTAG_915__HTMLTAG_916
___HTMLTAG_919__HTMLTAG_920___模式____HTMLTAG_921__HTMLTAG_922___說明____HTMLTAG_923__HTMLTAG_924___令牌聲明____HTMLTAG_925__HTMLTAG_926___
___HTMLTAG_929__HTMLTAG_930__HTMLTAG_931___委託___HTMLTAG_932__HTMLTAG_933__HTMLTAG_934___服務 B 知道服務 A 正在代表其使用者___HTMLTAG_935__HTMLTAG_936974MLTAG_41374MLTAG_sub sub = 使用者___HTMLTAG_941__HTMLTAG_942___
___HTMLTAG_943__HTMLTAG_944__HTMLTAG_945___模擬___HTMLTAG_946__HTMLTAG_947__HTMLTAG_948___服務 B 不知道 — 權杖與直接使用者要求相同___HTMLTAG_949__HTMLTAGML_9501114U41____MLTAG_949__HTMLTAGML_9501114251____42_421_U450_41TAGMLTAG1011_425_42____ act)
___HTMLTAG_959__HTMLTAG_960___8。 JWT 授權 (RFC 7523)HTMLTAG_961__HTMLTAG_962
允許客戶端使用受信任的頒發者發出的 JWT 斷言來取得存取令牌,而無需使用者互動。
HTMLTAG_967__HTMLTAG_968___8.1 流程___HTMLTAG_969__HTMLTAG_970
# External issuer (ví dụ: Azure AD, Google) cấp JWT cho client
# Client gửi JWT đến Keycloak để exchange lấy Keycloak access token
POST /realms/my-realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=eyJhbGciOiJSUzI1NiIs...& # JWT from external issuer
client_id=my-client&
client_secret=my-secret&
scope=openid
HTMLTAG_971__HTMLTAG_972___8.2 設定 JWT 授權___HTMLTAG_973__HTMLTAG_974
___HTMLTAG_976__HTMLTAG_977___領域設定 → 金鑰 → 新增外部發行者的簽章金鑰___HTMLTAG_980__HTMLTAG_981___
___HTMLTAG_982__HTMLTAG_983___或設定外部頒發者 身分提供者___HTMLTAG_986__HTMLTAG_987___
___HTMLTAG_988__HTMLTAG_989___客戶端必須啟用 服務帳戶角色___HTMLTAG_992__HTMLTAG_993___
HTMLTAG_995__HTMLTAG_996___9。為 MCP 伺服器設定 Keycloak___HTMLTAG_997__HTMLTAG_998
模型上下文協定 (MCP) 伺服器使用 OAuth 2.0 對用戶端進行身份驗證。 Keycloak 可以充當 MCP 生態系統的 授權伺服器.
HTMLTAG_1003__HTMLTAG_1004___9.1 MCP OAuth 2.0 流程___HTMLTAG_1005__HTMLTAG_1006
MCP 規格需要 OAuth 2.0 進行伺服器到伺服器和用戶端到伺服器驗證:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ MCP Host │ │ Keycloak │ │MCP Server│
│ (Client) │ │ (AuthZ) │ │(Resource)│
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ 1. Request │ │
│ auth info │ │
│───────────────────────────────>│
│ 2. Return │ │
│ auth metadata│ │
│<──────────────────────────────│
│ │ │
│ 3. Authorization Code Flow │
│ (hoặc Client Credentials) │
│───────────────>│ │
│ 4. Tokens │ │
│<───────────────│ │
│ │ │
│ 5. API call with access token │
│───────────────────────────────>│
│ 6. MCP Server validates token │
│ via Keycloak JWKS/Introspect│
│<──────────────────────────────│
HTMLTAG_1009__HTMLTAG_1010___9.2 為 MCP 主機建立客戶端___HTMLTAG_1011__HTMLTAG_1012
# MCP Host client — ứng dụng AI/LLM kết nối tới MCP servers
Client ID: mcp-host-app
Client type: OpenID Connect
Client authentication: ON (confidential)
Capability Config:
Standard flow: ON # Cho interactive MCP sessions
Service accounts roles: ON # Cho automated MCP operations
Access Settings:
Valid redirect URIs: http://localhost:3001/callback
Web origins: http://localhost:3001
Advanced:
PKCE Code Challenge Method: S256
Access Token Lifespan: 300 # 5 phút
HTMLTAG_1013__HTMLTAG_1014___9.3 為 MCP 伺服器(資源伺服器)建立客戶端___HTMLTAG_1015__HTMLTAG_1016
預編碼_24
HTMLTAG_1017__HTMLTAG_1018___9.4 為 MCP 操作建立範圍___HTMLTAG_1019__HTMLTAG_1020
預編碼_25
HTMLTAG_1021__HTMLTAG_1022___9.5 MCP 受眾映射器___HTMLTAG_1023__HTMLTAG_1024
# MCP Host client cần access token với audience = MCP Server
Client: mcp-host-app → Client scopes → Dedicated scope → Add mapper
Mapper Type: Audience
Name: mcp-server-audience
Included Client Audience: mcp-tool-server
Add to access token: ON
# Access token kết quả:
{
"iss": "http://localhost:8080/realms/my-realm",
"sub": "user-or-service-account-id",
"aud": ["mcp-host-app", "mcp-tool-server"],
"azp": "mcp-host-app",
"scope": "openid mcp:tools:read mcp:resources:read",
"mcp_permissions": ["tools:read", "resources:read"]
}
HTMLTAG_1025__HTMLTAG_1026___9.6 MCP 多伺服器的令牌交換___HTMLTAG_1027__HTMLTAG_1028
當 MCP Host 需要呼叫許多不同的 MCP 伺服器時,使用 Token Exchange 取得每個伺服器的代幣:
預編碼_27
HTMLTAG_1031__HTMLTAG_1032___9.7 MCP 用戶端策略___HTMLTAG_1033__HTMLTAG_1034
預編碼_28______HTMLTAG_1035__HTMLTAG_1036___10。練習___HTMLTAG_1037__HTMLTAG_1038
HTMLTAG_1039__HTMLTAG_1040___實驗室 1:客戶端策略 — 基線安全___HTMLTAG_1041__HTMLTAG_1042
___HTMLTAG_1044__HTMLTAG_1045___建立客戶端設定檔 基線安全性 與執行器:拒絕隱式授權、PKCE 強制執行器、安全簽章演算法___HTMLTAG_1048__HTMLTAG_1049___
___HTMLTAG_1050__HTMLTAG_1051___建立客戶端策略 執行基線,條件為___任何客戶端___HTMLTAG_1055__HTMLTAG_105677___
___HTMLTAG_1058__HTMLTAG_1059___測試:建立新客戶端並嘗試在沒有 PKCE 的情況下請求令牌 → 被拒絕___HTMLTAG_1060__HTMLTAG_1061___
___HTMLTAG_1062__HTMLTAG_1063___測試:嘗試開啟隱含串流 → 被拒絕___HTMLTAG_1064__HTMLTAG_1065___
HTMLTAG_1067__HTMLTAG_1068___實驗室 2:FAPI 2.0 合規性___HTMLTAG_1069__HTMLTAG_1070
___HTMLTAG_1072__HTMLTAG_1073___使用內建 FAPI 2.0 安全設定檔建立客戶設定檔___HTMLTAG_1074__HTMLTAG_1075___
___HTMLTAG_1076__HTMLTAG_1077___建立僅適用於具有 fapi-client___HTMLTAG_1079__HTMLTAG_1080__HTMLTAG_1081___ 角色的客戶端的策略
___HTMLTAG_1082__HTMLTAG_1083___使用簽章 JWT 驗證建立機密客戶端___HTMLTAG_1084__HTMLTAG_1085___
___HTMLTAG_1086__HTMLTAG_1087___使用 PAR + PKCE + DPoP 測試完整授權流程___HTMLTAG_1088__HTMLTAG_1089___
HTMLTAG_1091__HTMLTAG_1092___實驗室 3:客戶端密鑰輪換___HTMLTAG_1093__HTMLTAG_1094
___HTMLTAG_1096__HTMLTAG_1097___配置秘密輪換執行器(過期:60 秒,寬限期:30 秒用於測試)___HTMLTAG_1098__HTMLTAG_1099___
___HTMLTAG_1100__HTMLTAG_1101___建立機密客戶端 → 記錄機密 A___HTMLTAG_1102__HTMLTAG_1103___
___HTMLTAG_1104__HTMLTAG_1105___等待 60 秒 → 重新產生機密 → 記錄機密 B___HTMLTAG_1106__HTMLTAG_1107___
___HTMLTAG_1108__HTMLTAG_1109___驗證:秘密 A 在寬限期(30 秒)內仍處於活動狀態___HTMLTAG_1110__HTMLTAG_1111___
___HTMLTAG_1112__HTMLTAG_1113___驗證:寬限期後,只有秘密 B 處於活動狀態___HTMLTAG_1114__HTMLTAG_1115___
HTMLTAG_1117__HTMLTAG_1118___實驗 4:服務帳戶 + 令牌交換___HTMLTAG_1119__HTMLTAG_1120
___HTMLTAG_1122__HTMLTAG_1123___建立 3 個客戶端: frontend-app(公用)、api-gateway(機密 + 服務帳號) 支付服務(機密)___HTMLTAG_1130__HTMLTAG_1131___
___HTMLTAG_1132__HTMLTAG_1133___使用者透過 frontend-app 登入 → 接收存取權杖___HTMLTAG_1136__HTMLTAG_1137___
___HTMLTAG_1138__HTMLTAG_1139__HTMLTAG_1140___api-gateway從前端接收令牌,兌換新令牌支付服務___HTMLTAG_1143__HTMLTAGMLTA144442_____
___HTMLTAG_1146__HTMLTAG_1147___驗證:新令牌具有 aud:付款服務 和 act.sub:api-gateway___HTMLTAG_1151__13G1151__131151153_ML
___HTMLTAG_1155__HTMLTAG_1156___實驗 5:MCP 伺服器設定___HTMLTAG_1157__HTMLTAG_1158___
___HTMLTAG_1160__HTMLTAG_1161___建立領域 mcp-demo___HTMLTAG_1163__HTMLTAG_1164__HTMLTAG_1165___
___HTMLTAG_1166__HTMLTAG_1167___建立客戶端:mcp-host(機密)、mcp-tools-server(機密)HTHT70___MLG1721171___(機密)HTML
___HTMLTAG_1174__HTMLTAG_1175___建立客戶端範圍:mcp:tools:read、mcp:tools:execute___HTMLTAGML_1798HT
___HTMLTAG_1182__HTMLTAG_1183___為 mcp-host 設定受眾映射器 → 受眾 = mcp-tools-server____HTMLTAGML_18787878782__41878_____
___HTMLTAG_1190__HTMLTAG_1191___使用客戶端憑證流程取得令牌___HTMLTAG_1192__HTMLTAG_1193___
___HTMLTAG_1194__HTMLTAG_1195___驗證令牌內容:受眾、範圍、權限____HTMLTAG_1196__HTMLTAG_1197___
___HTMLTAG_1198__HTMLTAG_1199___使用 JWKS 端點模擬 MCP 伺服器驗證令牌___HTMLTAG_1200__HTMLTAG_1201___
HTMLTAG_1203__HTMLTAG_1204___實驗 6:簽章 JWT 用戶端驗證___HTMLTAG_1205__HTMLTAG_1206
___HTMLTAG_1208__HTMLTAG_1209___產生 RSA 金鑰對 (openssl)___HTMLTAG_1212__HTMLTAG_1213___
___HTMLTAG_1214__HTMLTAG_1215___使用驗證器建立機密用戶端 = 簽章 JWT___HTMLTAG_1217__HTMLTAG_1218__HTMLTAG_1219___
___HTMLTAG_1220__HTMLTAG_1221___將憑證上傳到Keycloak___HTMLTAG_1222__HTMLTAG_1223___
___HTMLTAG_1224__HTMLTAG_1225___編寫腳本來建立和簽署 client_assertion JWT___HTMLTAG_1226__HTMLTAG_1227___
___HTMLTAG_1228__HTMLTAG_1229___使用 client_assertion 而非 client_secret___HTMLTAG_1233__HTMLTAG_1232___client_secret___HTMLTAG_1233__HTMLTAG_1232___client_secret___HTMLTAG_1233__HTMLTAG_123443112353__
___HTMLTAG_1236__HTMLTAG_1237___驗證收到的令牌___HTMLTAG_1238__HTMLTAG_1239___