Azure API Managementで、異なるIdP間のOBO flowを実現できるのか?

このエントリは2026/03/27現在の情報に基づいています。将来の機能追加や変更に伴い、記載事項からの乖離が発生する可能性があります。

以前以下のようなエントリを書いたが、それを読んだ人から問い合わせをもらったのが、このエントリを書くきっかけ。

主の質問は以下の通り。

入口のJWT発行元と、OBOで取得したいJWTは別の発行元、しかも異なるIdPサービスもしくはソフトウェアという条件がある場合、Azure API Management (APIM) で、OIDC/OAuth 2.0のOBO (On-Behalf-Of flow) を実現することはできるか?できるとしたらどのような方法が考えられるか?

Microsoft Entraなど、1個のIdPだけで済むならともかく、SaaSや3rd party APIを使う場合には起こりえるので、調査しておくに超したことはなさそう。ただし、前回のエントリに記載した通り、APIMではOBO Flowをネイティブにはサポートしておらず、ポリシーを組み合わせて実現する必要があるので、注意が必要。今回の調査対象のIdPは以下とする。それぞれを組み合わせると12通り。

  • Microsoft Entra
  • Okta
  • KeyCloak
  • Auth0

結論から言うと、なかなか渋い結果で、こういうもんかね、という感想。

  • これらの組み合わせではCross IdP OBO flowは難しい。
  • 条件付きで実現可能な組み合わせはあるが、現時点では Auth0 CTE が Early Access、Keycloak Legacy V1 が Preview であり、いずれも GA の安定機能ではない。そのため、本番採用には機能変更リスク・サポート条件・運用負荷を個別に評価する必要がある。

大前提

APIM は OBO / token exchange の“実行場所”にはなり得るが、APIM 自身は Security Token Service (STS) ではない。APIM が標準で提供するのは以下。

  • 入口トークンの検証
  • 外部IdPへのHTTP呼び出し
  • 接続済みOAuth資格情報の取得
  • Managed Identity による Microsoft Entra トークン取得

APIMは、OIDC準拠のあらゆるIdPからのJWTを検証し、任意のトークンエンドポイントに対してHTTP POSTリクエストを発行できるため、実現可否は「APIM にできるか」ではなく、「OBO / token exchange の相手IdPが、その入口JWTを subject_token / assertion として受け付けるか」で決まる。

各IdPのOBOトークン交換におけるトークンの制限は以下の通り。

IdPのOBOトークン交換制限・前提条件
Microsoft EntraのOBOMicrosoft Entra の OBO 一次情報では、assertion は middle-tier API に送られたアクセス トークンであり、その aud は OBO 要求を行うアプリでなければならないとされている。
このため、Okta / Auth0 / Keycloak が発行したトークンを直接持ち込むクロス issuer OBO については、少なくとも一次情報ベースの supported path には確認できない。
Microsoft identity platform and OAuth2.0 On-Behalf-Of flow – Microsoft identity platform | Microsoft Learn
Okta のtoken exchangeOkta の token exchange 一次情報は、1 つの custom authorization server または同一 Okta tenant 内の trusted servers を前提としている。
したがって、Entra / Auth0 / Keycloak 発行トークンを subject token とする直接クロス issuer 交換は、少なくとも公式ドキュメント上のサポート範囲外とみなすのが安全。
Set up OAuth 2.0 On-Behalf-Of Token Exchange | Okta Developer
Keycloak の標準 token exchange (V2) 同一 realm 内の Keycloak 発行トークンだけが対象
Keycloak のLegacy Token Exchange V1(preview)IdP 登録とアカウント リンクがあれば、外部 IdP トークンを Keycloak トークンへ交換可能
Auth0のCustom Token Exchange (Early Access)Custom Token Exchange(Early Access) は、subject token を検証して Auth0 ユーザーにマッピングするユーザー実装の Action を通じて、任意のトークン形式 を受け入れる

APIMのCredential Managerが一般的な cross-IdP per-request token exchange の代替ではない理由

APIM Credential Manager は、接続済み OAuth 2.0 backend / SaaS API への delegated access を簡素化する機能であり、一般的な cross-IdP per-request token exchange の代替ではない。とくに get-authorization-context の identity-type=jwt は Microsoft Entra JWT を前提としているため、本件のような非 Entra 入口 token の汎用処理には向かない。

理由詳細
静的かつ事前構成された接続であり、リクエストごとの交換ではないCredential Manager は、あらかじめ確立された接続に基づいて動作する。
attended(ユーザー委任) シナリオでは、
❶構成済みユーザーは一度だけサインインして同意すればよく、その後 API Management インスタンスが接続を作成し管理する
❷実行時には、get-authorization-context ポリシーが保存済みトークンを取得し、期限切れであれば更新する
これは、各受信リクエストの JWT を都度ターゲット IdP 用の新しいトークンに交換する OBO とは根本的に異なる。Credential Manager は、そのようなリクエスト単位の交換を行わない。
Unattended モードでは、リクエストごとのユーザー コンテキストがないunattended シナリオでは、API 呼び出しはユーザー コンテキストに関連しない事前構成済み接続を利用するため、すべてのユーザーに同じデータが返される。
つまり、1 つの保存済みトークンがすべての呼び出し元に使い回されてしまう。OBO は定義上、呼び出し元ユーザーのアイデンティティ をダウンストリーム トークンに伝播させる必要があるが、このモードではそれが実現できない。
Attended モードは Microsoft Entra の ID に限定されるAttended シナリオでは、Microsoft Entra ユーザーまたはグループ ID を代理して接続へのアクセスを有効化するのであって、Okta、Auth0、Keycloak で認証されたユーザーは、この委任メカニズムに直接参加できない。そのため、「入口トークンが非 Entra IdP から来る」という本件ユースケースの前提条件を満たせない。

Credential Manager は、SaaS バックエンド接続や Logic Apps 的な統合を含む、バックエンド OAuth 2.0 API のトークン ライフサイクル管理を簡素化するが、OBO を定義づける リアルタイムかつアイデンティティ保持型のトークン交換 は実行しない。Credential Manager を Cross-IdP 委任に使うと、(unattended では)呼び出し元のアイデンティティが失われるか、(attended では)呼び出し元が最初から Microsoft Entra の ID を持っている必要がある。


IdP ごとのトークン交換機能について

a) Microsoft Entra

Microsoft identity platform の OBO フローは、ユーザーの ID と権限をリクエスト チェーン全体に渡すために、/oauth2/v2.0/token エンドポイントでアクセス トークンを交換する。主なパラメータと制約は以下の通り。

パラメータ値 / 要件
grant_typeurn:ietf:params:oauth:grant-type:jwt-bearer
assertionOBO 要求を行うアプリの client_id と一致する aud クレームを持つアクセス トークンであること。
「アプリは別のアプリ向けトークンを redeem できない(たとえば、クライアントが API に Microsoft Graph 向けトークンを渡した場合、その API は OBO でそれを redeem できない)」
requested_token_useon_behalf_of
ユーザー主体のみ「OBO フローはユーザー主体に対してのみ動作する」。サービス プリンシパルの app-only トークンは OBO で交換できず、代わりに Client Credentials を使う必要がある。
カスタム署名キー「カスタム署名キーを持つアプリケーションは OBO フローの中間 API として使えない」

Cross-IdP シナリオにおける決定的制約

assertion は、Entra 発行の ユーザー アクセス トークンであり、その aud が中間層アプリの Azure AD client_id と一致している必要がある。Okta、Auth0、Keycloak からの JWT は、それぞれ外部 issuer(iss)、外部 audience 形式、外部署名キーを持つため、Entra のトークン エンドポイントでは検証できず、OBO 要求は拒否される。jwt-bearer グラントは Microsoft 独自拡張であり、RFC 8693 準拠ではない

b) Okta

Okta は RFC 8693 の token exchange(grant_type=urn:ietf:params:oauth:grant-type:token-exchange)を実装しているが、その適用範囲は明確に制限されていて、「On-Behalf-Of Token Exchange は 1 つの custom authorization server で利用できる。また、同一 Okta テナント内の他の custom authorization servers 間でも利用できる」とされている。

構成要件:

  • サービス アプリで Token Exchange を有効化する必要がある(Grant type セクションの Advanced から Token Exchange を選択)
  • Authorization server 側で custom scopes を作成する必要がある。「サービス アプリ起点の token exchange では offline_access や OpenID Connect scopes は含められない。つまり refresh token や ID token は要求できない」
  • 同一テナント内の複数 authorization server 間で交換する場合は Trusted servers を構成する必要がある

外部トークン拒否は明示されている。Okta の Knowledge Base では、token exchange 時の "subject token is invalid" エラーの原因として、以下が挙げられており、推奨される確認事項として「issuer claim にある authorization server が、token call で使用している authorization server と同じであることを確認する」との記載がある。

  1. exp の期限切れ
  2. aud 不一致 — 「subject_token の aud が token exchange を行うアプリの client_id ではない」
  3. issuer 不一致 — 「トークンの iss が、token endpoint で使用している authorization server と異なる」

そのため、同一 Okta テナント内の authorization server 以外から発行されたトークンは、(3) により拒否され、Cross-IdP 交換は不可能。

c) Auth0

Auth0 は Custom Token Exchange を提供している(Enterprise および B2B Pro 向け Early Access)。この機能は「RFC 8693 に従い、アプリケーションが既存トークンを Auth0 トークンへ交換できるようにする」もので、想定ユースケースとしては、「別 audience 向け Auth0 トークンの取得」「外部 identity provider との統合」「Auth0 への移行」が挙げられている。

仕組みは完全にプログラマブル。

  • 各 token exchange 要求は、Custom Token Exchange Profile にマップされ、その Profile は 1 つの Action(Auth0 のサーバーレス関数)によって制御
  • Action の中で開発者は、subject_tokendecode / validate し、さらに 認可判断を行い、ユーザーを設定する コードを書く
  • 「Custom Token Exchange で使用する subject token は、Action コードが解釈できる限り、任意のトークン形式・型でよい。受け取って受け入れるトークンについて、強固な検証を実装しなければならない」と明記されている

現在の制約(Early Access):

  • MFA API メソッド(challengeWith() / EnrollWith())は未対応
  • import mode ON の Custom DB Connections は setUserByConnection() では未対応
  • actor_tokenactor claim などの委任情報は未対応
  • サードパーティおよび non-OIDC conformant クライアントは未対応
  • 非対話型フローでは同意を取得できないため、ターゲット API で Allow Skipping User Consent の有効化が必要

Auth0 ドキュメントの “Re-use an external authentication provider” 例は、Cross-IdP OBO に直接対応するパターン。パートナー アプリのユーザーが外部 IdP で認証され、その外部 ID token を subject_token として Auth0 の /oauth/tokengrant_type=urn:ietf:params:oauth:grant-type:token-exchange で渡し、Auth0 access token に交換する。Action は外部トークンを検証し(たとえば外部 IdP の JWKS を利用)、api.authentication.setUserByConnection() を通じて外部 ID を Auth0 ユーザーへマップする。

d) Keycloak

Keycloak はトークン交換を 2 系統で実装している。

機能Standard Token Exchange V2Legacy Token Exchange V1
既定状態既定で有効既定で無効(preview)
対応ユースケース(1) Internal のみ: 同一 realm 内 Keycloak token → Keycloak token4 つすべて:
(1) internal
(2) KC→external
(3) external→KC
(4) impersonation
互換性正式サポート、今後も維持将来の Keycloak バージョンで後方互換が保証されない可能性がある
依存機能クライアント スイッチ有効化のみFine-grained admin permissions version 1 (FGAP:v1) が必要

Cross-IdP OBO で関係するのは (3) external token → Keycloak token。要求を行うクライアントは、適切な token exchange 権限を持つ confidential client である必要がある。

external-to-internal 交換では subject_issuer パラメータが必要。これは「その realm に設定された Identity Provider の alias、または特定の Identity Provider で設定された issuer claim identifier」でなければならない。subject_token_typeurn:ietf:params:oauth:token-type:access_token または urn:ietf:params:oauth:token-type:jwt のいずれかでなければならない。

Keycloak のドキュメントにある external-to-internal 交換の curl 例では、以下のように指定している。

-d "subject_issuer=myOidcProvider" \
--data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token"

外部 IdP は Keycloak に OIDC Identity Provider として登録されている必要があり、交換対象ユーザーは Keycloak 側とアカウント リンク済みでなければならず、リンクがなければ交換は失敗する(SAML の identity provider は token exchange ではサポートされない)。

さらに FGAP:v2 は「token exchange permissions をサポートしない。これは token-exchange が“管理権限”ではないという考えに基づき、FGAP:v2 に追加する予定はない」とされている。したがって Legacy V1 の利用には、古い FGAP:v1 を有効化する必要がある。


Cross-IdP OBO 実現可否マトリクス

ターゲットが Microsoft Entra または Okta の組み合わせはすべて不可能。ターゲットが Auth0 または Keycloak の組み合わせは、条件付きで可能。

#Entry IdPOBO Target IdPFeasible?制約 / 有効化要件
1Microsoft EntraOktaNoOkta は非 Okta トークンを拒否(issuer mismatch)
2OktaMicrosoft EntraNoEntra は自分自身のトークンを assertion として要求
3Microsoft EntraKeycloakDependsKeycloak Legacy V1(preview)+ IdP 登録 + (既存ユーザーに解決される場合は)account linking
4KeycloakMicrosoft EntraNoEntra は自分自身のトークンを assertion として要求
5OktaKeycloakDependsKeycloak Legacy V1(preview)+ IdP 登録 + (既存ユーザーに解決される場合は)account linking
6KeycloakOktaNoOkta は非 Okta トークンを拒否(issuer mismatch)
7Microsoft EntraAuth0DependsAuth0 Custom Token Exchange(Early Access)+ Action コード
8Auth0Microsoft EntraNoEntra は自分自身のトークンを assertion として要求
9OktaAuth0DependsAuth0 Custom Token Exchange(Early Access)+ Action コード
10Auth0OktaNoOkta は非 Okta トークンを拒否(issuer mismatch)
11KeycloakAuth0DependsAuth0 Custom Token Exchange(Early Access)+ Action コード
12Auth0KeycloakDependsKeycloak Legacy V1(preview)+ IdP 登録 + (既存ユーザーに解決される場合は)account linking

ターゲット IdP ごとの詳細分析

a) ターゲット: Microsoft Entra ID(#2, #4, #8)— No

Entra の OBO エンドポイントは、assertion について、中間層 API に送られたアクセス トークンであり、かつその aud はこの OBO 要求を行うアプリ(client-id で表されるアプリ)でなければならない。grant_typeurn:ietf:params:oauth:grant-type:jwt-bearerであり、これは Microsoft 独自拡張で、RFC 8693 準拠ではない。外部トークンを示す subject_issuer のようなパラメータは存在しない。

IdPissuer
Oktahttps://{org}.okta.com/oauth2/{serverId}
Auth0https://{tenant}.auth0.com/
Keycloakhttps://{host}/realms/{realm}

Microsoft Entra については、OBO 一次情報が assertion を middle-tier 宛て access token と定義しており、外部 issuer token を直接持ち込む supported path は確認できない。したがって、Okta / Auth0 / Keycloak token を入力にする direct cross-issuer OBO は、少なくとも公式ドキュメント上は非サポート扱いが妥当である。

対話的フェデレーションで代替できそうに見えるが、そうはいかない。

確かにOkta を Entra で SAML 2.0 または OIDC IdP として構成できるが、この構成はブラウザベースの SSO であり、API レベル OBO token exchange ではない。Auth0 や Keycloak についても同様で、SAML/OIDC federation はインタラクティブなログイン パスを作るだけで、プログラマブルな token exchange grant にはならない。

b) ターゲット: Okta(#1, #6, #10)— No

Okta については、token exchange の一次情報が単一 custom authorization server または同一 tenant 内 trusted servers を前提としている。したがって、外部 issuer token を直接 subject token とする交換は、少なくとも公式ドキュメント上のサポート範囲外とみなすのが安全である。

外部 JWT が subject_token として渡されると、Okta はそのトークンに対して、以下の3点を検証する。

(1) 期限切れ
(2) 呼び出し元アプリの client_id に対する audience 一致
(3) token endpoint を処理している authorization server に対する issuer 一致

Entra、Keycloak、Auth0 からのトークンは issuer チェックで失敗し、

{
  "error": "invalid_grant",
  "error_description": "subject token is invalid"
} 

を返す。

外部 IdP トークンを登録できる Trusted servers のような仕組みはない。Trusted servers はあくまでテナント内複数 authorization server 間のユースケース専用。

c) ターゲット: Keycloak(#3, #5, #12)— Depends

これらの組み合わせは、Keycloak の Legacy Token Exchange V1 により実現可能。これはユースケース(3)「外部トークンを Keycloak トークンに交換する」をサポートするためであるが、 preview であり、既定では無効である点に注意が必要。

Keycloak 側構成(3 パターン共通):

1Legacy Token Exchange を有効化Legacy Token Exchange V1 は preview で既定無効であり、Keycloak docs に従って preview / token-exchange 機能を有効化する必要がある。
あわせて、V1 を使うには FGAP:v1 が必要。具体的な起動フラグは Keycloak バージョン差分の影響を受けうるため、利用バージョンの公式 docs を参照して決めること。
Configuring and using token exchange – Keycloak
2外部 IdP を OIDC Identity Provider として target realm に登録【Entra ID が entry の場合】
Entra の OIDC discovery URL(https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration)、Entra app registration から取得した client ID / secret を設定し、alias(例: azure-ad)を割り当てる
【Okta が entry の場合】
Okta の OIDC discovery URL、client credentials、alias(例: okta)を設定
【Auth0 が entry の場合】
Auth0 の OIDC discovery URL(https://{tenant}.auth0.com/.well-known/openid-configuration)、client credentials、alias(例: auth0)を設定
Configuring and using token exchange – Keycloak
3外部ユーザーと Keycloak ユーザーの account linking を確立Keycloak は、外部 IdP 登録を前提に external-to-internal exchange を行えるが、account linking は常時必須ではなく、既存ユーザーに解決される場合の要件である。
一方、既存ユーザーにマップされない場合は、新規ユーザーの import が行われる可能性がある。
4confidential client を構成APIM または broker service を表す confidential client を Keycloak に作成し、token exchange の権限を与える。

APIM ポリシー実装:

<validate-jwt> — entry IdP の OIDC metadata に対して受信トークンを検証し、issaud、署名を確認。
<send-request> — Keycloak の token endpoint に POST する。

POST /realms/{realm}/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
client_id={keycloak_confidential_client_id}&
client_secret={keycloak_client_secret}&
subject_token={incoming_jwt_from_entry_idp}&
subject_issuer={alias_of_external_idp_in_keycloak}&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
requested_token_type=urn:ietf:params:oauth:token-type:access_token

subject_issuer は、登録済み外部 IdP の alias と一致している必要がある。標準の交換リクエスト形式は Keycloak ドキュメントに示されており、外部トークンの場合はこれに subject_issuer が加わる。

レスポンス トークンを取り出す
Keycloak は access_tokenexpires_in(例: 300)、token_typeBearer)、issued_token_typescope を含む JSON を返す。<set-variable><set-header> を使って、この新しいトークンをバックエンド リクエストに付与する。

send-request + トークン抽出の APIM ポリシー パターンは、Azure API Management and OAuth tokens for multiple backend services – Ludovic Médard というエントリでカバーしている、Azure AD 同一 IdP OBO の例で実証されている。そこでは、受信 Authorization ヘッダーから bearer token を取り出し、<send-request> で token endpoint に POST し、JSON レスポンスから access_token を取り出して、バックエンド転送前に Authorization ヘッダーを上書きしている。Cross-IdP の Keycloak ケースでも、token endpoint と grant parameters(token-exchangesubject_tokensubject_issuer)が異なるだけで、パターン自体は同じ。

トレードオフ:

preview 安定性リスクLegacy V1 は将来の Keycloak バージョンで後方互換が保証されない可能性がある。
本番導入時はアップグレードで破壊的変更が起こりうることを前提にする必要がある。
account linking の運用負荷最初の交換が成功する前に、各ユーザーが Keycloak とリンク済みである必要があるため、初回ログインまたは一括プロビジョニングのようなオンボーディング ステップが必要。
SAML IdP は対象外token exchange で使える外部 IdP は OIDC のみ。SAML ベース構成は不可。
FGAP:v1 依存FGAP:v1 を有効化することで管理面の複雑性が増す。
Keycloak チームは FGAP:v2 へ token exchange permissions を追加する予定はないと明言しており、これは一時的ではなく構造的制約として捉えるべき。

ターゲット: Auth0(#7, #9, #11)— Depends

これらの組み合わせは、Auth0 の Custom Token Exchange(Early Access)で実現可能です。Auth0 は、テナントで機能が有効化され、Custom Token Exchange Profile と Action が構成されていれば、任意の外部トークンを subject_token として受け入れます【1†L10-L25】。

Auth0 側構成(3 パターン共通)

1Custom Token Exchange を有効化対象 Auth0 テナントでこの Early Access 機能が有効になっているか確認(Enterprise および B2B Pro 向け機能)
2Custom Token Exchange Profile を作成交換後トークンを受け取るアプリケーションに対して Profile を作成。
各 Profile は 1 つの Action と関連付けられる。
3Action(Node.js)を実装外部 IdP からの subject_token を検証
外部 IdP の JWKS エンドポイントを取得し、JWT の署名、issaudexp、その他必要な claim を検証。Auth0 は jose ライブラリを利用した JWKS ベース検証のコード例を提供
認可ポリシーを適用
交換を許可するかどうかを判定(例: scope、roles、domain 制約など)。拒否する場合は api.access.deny() を利用。
Auth0 側のユーザーを設定
外部ユーザーを Auth0 の特定接続内ユーザーへマッピングするには api.authentication.setUserByConnection()、既存 Auth0 ユーザー ID を使う場合は api.authentication.setUserById() を利用
ユーザーが存在しない場合は creationBehavior: 'create_if_not_exists' を利用可
4ターゲット API を構成非対話型フローでは consent を取得できないため、Auth0 の API リソース側で Allow Skipping User Consent を有効にしておく必要がある

APIM ポリシー実装:

<validate-jwt> — entry IdP の OIDC metadata に対して受信トークンを検証
<send-request> — Auth0 の token endpoint に POST する

POST https://{auth0_domain}/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token={incoming_jwt_from_entry_idp}&
subject_token_type={custom_or_standard_type}&
audience={auth0_api_identifier}&
scope={desired_scopes}&
client_id={auth0_client_id}&
client_secret={auth0_client_secret}

subject_token_type は標準 URN でも独自識別子でもよく、Profile 定義と一致していればよい。Auth0 は要求を対応する Custom Token Exchange Profile にマップし、Action を実行する。

レスポンスを取り出す
成功時、Auth0 は、マッピングされたユーザーに対する Auth0 発行の access token / ID token / refresh token を返すので、これを取り出してバックエンド リクエストへ付与する。

トレードオフ

Early Access ステータスまだ GA ではないため、GA 前に挙動が変わる可能性がある。
セキュリティ責任が開発者にある受け取って受け入れるトークンについて、強固な検証を実装しなければならない。そうしないと spoofing や replay attack などの攻撃に対して脆弱になる。
Auth0 では検証責任のすべてを Action 開発者が負う。
actor_token / delegation chain 非対応 Early Access 版では「Specific delegation support(例: actor_tokenactor claim)」が未対応。そのため、「元のユーザー + 代理動作するサービス」という完全な OBO 委任チェーンを Auth0 トークン上で表現できない。
一方向のみAuth0 Custom Token Exchange は Auth0 トークンを生成するだけであり、Auth0 トークンを外部 IdP トークンへ交換することはできない。
Enterprise/B2B Pro 必須下位プランでは利用不可

IdP 間プロトコル比較

属性Microsoft EntraOktaAuth0
(Custom Token Exchange)
Keycloak
(Legacy V1)
Grant typejwt-bearertoken-exchangetoken-exchangetoken-exchange
入力トークン パラメータassertionsubject_tokensubject_tokensubject_token
外部 IdP トークン受入NoNo
(同一テナント内のみ)
Yes
(任意形式、Action による)
Yes
subject_issuer により)
外部トークンの検証N/AN/AAction コードで開発者が実装検証処理が Keycloak 側 IdP 設定に寄る
ユーザー マッピングN/AN/A開発者実装(setUser API)account linking による自動
RFC 8693 準拠No
(独自 jwt-bearer
Yes(ただし同一テナント内に限定)Yes部分的 / loose implementation(preview, delegation semantics は未サポート)
機能成熟度GAGAEarly AccessPreview

ポイント

  • Okta と Keycloak はともに RFC 8693 の token-exchange grant を使い、Auth0 も RFC 8693 に従うが、Okta は適用範囲を同一テナント内に制限しているため、Cross-IdP では使えない。
  • Entra は独自の jwt-bearer grant を使うため、RFC 8693 ベースの exchange と根本的に非互換。
  • Auth0 は最大の柔軟性(任意トークン形式、任意検証ロジック)を提供するが、その分セキュリティ責任を全面的に開発者へ委ねる。
  • Keycloak は、外部 IdP 登録を前提に external-to-internal exchange を行えるが、account linking は常時必須ではなく、既存ユーザーに解決される場合の要件。
  • 条件付きで可能な 2 つのターゲット IdP(Auth0 と Keycloak)のいずれも、現時点で GA の完全サポート機能ではない。

APIM が果たす「プロトコル媒介層」としての役割

このアーキテクチャにおいて、APIM は次の 2 つのポリシーを提供する。

Policy
<validate-jwt>OIDC metadata URL、期待する issaud を指定することで、任意の OIDC 準拠 IdP の JWT を検証する。これは Entra、Okta、Auth0、Keycloak のトークンに対して同じように機能する。
<send-request>任意の token endpoint に対してカスタム form パラメータを持つ HTTP POST を送信し、受信トークンを使って token exchange リクエストを構築できる。

このパターンは、同一 IdP(Entra → Entra)の OBO シナリオですでに実証済み。APIM は受信 Authorization ヘッダーから Bearer token を変数へ取り出し、それを assertion として https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/tokengrant_type=urn:ietf:params:oauth:grant-type:jwt-bearer などのパラメータ付きで send-request し、JSON レスポンスから access_token を取り出してバックエンドへ送る前に Authorization ヘッダーを上書きする。

OBOトークンを逐一取得するのは高コストなので、キャッシュに一定期間保持して毎回 token exchange を行うことによる約 250ms のオーバーヘッドを避けることも推奨事項。具体的には以下のあたり。

  • ユーザーごとOBO トークンを 3300 秒までキャッシュ
  • unique_nameclientId の組み合わせでユニークにする

Azure API Management and OAuth tokens for multiple backend services – Ludovic Médard

このsend-request パターンは Cross-IdP シナリオでもそのまま使える。置き換えるのは、ターゲット IdP の token endpoint URL、適切な grant_type(Keycloak/Auth0 なら token-exchange)、および必要パラメータ(subject_tokensubject_issuer など)だけ。APIM の能力自体は制約ではなく、制約はターゲット IdP がその外部トークンを受け入れるかどうかである。


このような説明をしたところ、更問をもらったのだが、長くなったので次のエントリに記載する。

Resources

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください