1. トークン交換(Token Exchange)の基本概念
マイクロサービスアーキテクチャ(MSA)環境で、複数のサービス間で権限を委譲したりトークンを再発行したりする必要がある場合、Keycloakが提供するトークン交換(Token Exchange)機能は非常に有用なソリューションです。これは、認証済みのクライアントが既存のトークンを提出すると、Keycloakがそれを検証した後、送信先に適した新しい権限と対象を持つトークンに交換してくれる技術です。サービス間の信頼関係を明示的に定義し、権限の範囲を制御できるため、エンタープライズセキュリティの中核基盤となります。
2. 連携要件とImpersonationの採用
最近のプロジェクトの進行中、すでに他社プラットフォームで認証を完了したユーザーが自社サービスにアクセスする際、ログイン画面や別途の追加ログイン処理なしで利用できるようにしてほしいという要件がありました。ユーザーが二度ログインせずに済む、シームレスなUXを実現することが課題でした。
正統なKeycloak V2標準エンジンを適用しようとしましたが、技術的な制約に直面しました。標準仕様では外部サービスの実際のログイン証明書(元のトークン)が必須ですが、パートナー企業はセキュリティポリシー上、自社トークンを共有できず、「ユーザー固有ID(識別子)」のみを渡せる状況でした。
実際のトークンなしで識別情報だけを使い、追加ログインなしで通過させる必要があったため、標準エンジンの導入は不可能でした。そこで、追加のカスタムモジュール開発なしで要件を満たすため、バックエンド資格情報とユーザーID文字列だけでトークンを発行できる旧式の仕様(V1 Direct Naked Impersonation)による代理メカニズムを選択しました。内部インフラを保護するため、前段に「セキュリティプロキシ(Bridge Gateway)」を配置し、バックチャネルでトークンを取得して画面に渡す構成を確立しました。
3. Keycloakの設定:クライアントを接続する
安全なトークンの代理発行のため、Keycloakコンソールで要求元(Requester)クライアントと受信先(Target)クライアント間の明示的な信頼関係を定義する必要があります。
-
外部サービス用クライアント(Requester):クライアント認証をオン(Confidential)に設定し、マスターシークレットキーを内部に秘匿します。旧式のV1メカニズムを適用するため、サーバーレイヤーで旧式の詳細管理権限(FGAP:v1)仕様を有効化します。
-
内部MSA用クライアント(Target):認可と画面を担当するクライアントの権限メニューでtoken-exchangeを有効化します。ポリシー(Policy)を作成し、外部プロキシクライアントだけがトークンを代理して交換できるようにマッピングします。
4. バックエンド実装:トークンリクエスト仕様
プロキシサーバー(Spring Boot)は外部システムからのリクエストを検証した後、安全にKeycloakエンドポイントを呼び出すブリッジコードを実行します。旧式のV1仕様に基づくAPIペイロードの定義は次のとおりです。
-
エンドポイントURL: POST /realms/{realm-name}/protocol/openid-connect/token
-
ヘッダー仕様: Content-Type: application/x-www-form-urlencoded, Authorization: Basic [Base64(ID:Secret)]
トークン発行に必須のパラメーター定義
|
パラメーター名 |
設定値および例 |
説明 |
|---|---|---|
|
grant_type |
urn:ietf:params:oauth:grant-type:token-exchange |
プロトコル仕様の明示 |
|
requested_subject |
user_internal_idx_01 |
代理発行を受ける内部ユーザー固有ID |
|
requested_token_type |
urn:ietf:params:oauth:token-type:access_token |
アクセストークンを要求することの明示 |
|
audience |
internal-msa-core |
不要な権限を削減するダウンスコーピングを誘発 |
Keycloakの検証が成功すると、レスポンスデータからaccess_tokenを抽出します。このトークンにはユーザーのビジネス内部ロール(ROLE_USERなど)のみが注入され、プロキシはこれを外部サービス経由でユーザーのブラウザーに設定した後、リダイレクトを実行します。
5. 頻繁に発生するエラーと解決方法
実運用およびデプロイ段階で遭遇する3大ランタイムエラーへの対応ハンドブックです。
-
HTTP 404 Not Foundエラー:旧式のドキュメントを参考にしてエンドポイントアドレスに/authパスを含めた場合に発生します。最新バージョンではデフォルトのコンテキストパスから/authが削除されているため、省略する必要があります。
-
invalid_clientエラー:リクエストを送信するプロキシクライアント自体の設定で、トークン交換仕様に関するオプションが有効化されていない場合に発生するため、コンソールで該当するトグルスイッチを再確認する必要があります。
-
403 Forbidden / not_allowedエラー:クライアント間の信頼権限ポリシーが失われた場合に発生します。最終的な送信先となるTargetクライアントの権限メニューで、要求元クライアントがポリシーサブセットとして登録されているか確認する必要があります。
6. レガシー(V1)方式の限界と実務的な妥協点
本プロジェクトで最新のV2標準エンジンではなく旧式の仕様(V1 Direct Naked Impersonation)を採用したのは、外部連携環境の制約を克服するための意図的なアーキテクチャ上の選択でした。
Keycloak V2標準エンジンは、交換対象となる元のトークンの提出を必須仕様としています。しかし、連携対象である外部パートナー企業は、自社のセキュリティポリシー上、ユーザーセッショントークンを共有できず、「ユーザー固有ID」のみを提供できるという技術的な限界がありました。元のトークンがない状況で、プロキシサーバーに別途暗号化トークン生成システムを追加構築することなく、「追加ログイン処理の排除」という顧客企業の要件を迅速に満たすには、ユーザーIDだけでトークンを発行できる旧式のV1仕様が唯一の実務的な代案でした。
旧式の仕様が持つ潜在的なリスクは、インフラレイヤーの多層防御体制によって相殺しました。サーバーネットワーク(M2M)と画面ネットワーク(UI)の権限を厳格に二重分離し、ブラウザーに露出するトークンの有効期間を3~5分の短命トークンに制限することで、窃取の脅威を抑制しました。今後、Keycloakエンジンのアップデートに伴い、標準V2体制へ移行する課題は残されていますが、限られたリソースの中で外部企業との連携仕様に手を加えず、ビジネス目標を達成するための最も現実的なエンジニアリング上の妥協点でした。
7. おわりに
今回のプロジェクトは、B2B連携においてセキュリティとユーザーの利便性を同時に確保することが、いかに難しい作業であるかを改めて確認する機会となりました。外部インフラの制約下で実務的に最善のアーキテクチャを検討し、見つけていくプロセスそのものが大きな資産となりました。本連携事例が、マイクロサービス環境でKeycloakベースの認証インフラを検討している方々にとって、少しでも実務的な参考資料となれば幸いです。
参考資料
https://www.keycloak.org/securing-apps/token-exchange
oshua