新しい顧客ごとに Entra External ID(旧 Azure AD B2C 相当の CIAM テナント)を自動で増やし、アプリ登録やサインアップ/サインイン用ユーザーフローまで一気通貫で作りたい――そんなニーズは SaaS ベンダーでは珍しくありません。本記事では「ホステナントから完全自動化したい」という要件を前提に、なぜ 100%自動化はできないのか、そのうえでどこまでなら現実的に自動化できるのかを、実装レベルの観点で整理します。
Entra External ID(CIAM)テナント自動化の前提整理
まずは用語と前提をそろえておきます。
ホステナントと CIAM テナント(顧客テナント)
ここでいう構成は次のようなイメージです。
- ホステナント:自社のメインの Microsoft Entra テナント。ここに運用チームがログインし、CI/CD から Azure / Graph API を叩く。
- CIAM テナント(External tenant / Azure AD for customers):顧客向けアプリだけを収容する専用テナント。顧客のエンドユーザー(B2C に近い意味)がサインインする。
Microsoft は外部顧客シナリオ向けに、専用の External ID テナント(旧 Azure AD B2C の後継)を使うことを推奨しており、このテナントは Azure Resource Manager の Microsoft.AzureActiveDirectory/ciamDirectories リソースとして作成できます。
自動化でやりたいこと
典型的な「全部自動化したい」シナリオは次の 3 ステップです。
- ホステナントから 新しい Entra External ID(CIAM)テナントを作成
- そのテナント上に アプリ登録(App registration) を作成
- サインアップ/サインインなどの ユーザーフロー(user flow)を作成
もちろん、すべてを 人間のクリックなし(ノンインタラクティブ)で完了したい わけですが、ここに大きく立ちはだかるのが マルチテナントアプリに対する「テナント全体の管理者同意(admin consent)」 です。
「完全自動化」の可否をざっくり整理
| 処理 | 完全自動化の可否 | 理由/ポイント |
|---|---|---|
CIAM テナント作成(ciamDirectories) | ◯ 自動化可能 | ARM / Bicep / REST / Terraform で作成可能。権限があれば人手不要。 |
| マルチテナントアプリへの「テナント全体の管理者同意」 | ✕ 自動化不可 | 設計上、管理者がサインインして明示的に同意する必要あり(悪意あるアプリ拡散防止)。 |
| 管理者同意後のアプリ・ユーザーフロー構成 | ◯ 自動化可能 | Graph API(アプリケーション許可)を使えばヘッドレスで操作可能。 |
つまり、テナント作成~ユーザーフロー構成のうち、「テナント全体の管理者同意」だけは必ず人が一度は介在するというのが現実です。
なぜ「サイレントログインでの管理者同意」は存在しないのか
「admin consent を自動で押してくれる API ってないの?」という疑問はよく出ますが、現状 そのような API は存在せず、今後も出る可能性は極めて低いと考えておくのが安全です。
- テナント全体の管理者同意は、そのテナントの全ユーザーのデータや操作にアプリがアクセスできる可能性がある非常に強い権限。
- これを「別テナントから勝手に」自動付与できてしまうと、悪意あるマルチテナントアプリが一斉感染のように広がってしまうリスクがある。
- そのため Microsoft は、Global Administrator や Cloud Application Administrator などのロールを持つユーザーが、サインインしたうえで admin consent を行うことを前提としています。
要するに、信頼境界(ホステナントと新テナントの間)を超えて「勝手に承諾」することはできず、どこかで テナント側の管理者が署名する必要がある、という設計思想です。
現実解:手動は「1 テナントあたり 1 回」に集約する
完全自動化は無理でも、「1 テナントにつき 1 回だけ管理者がクリック」にまで縮退できれば、運用上はかなり楽になります。
ここで選択肢になるのが次の 2 方式です。
| 項目 | 方式 A:ホステナントのマルチテナントアプリ+管理者同意 | 方式 B:各 CIAM テナントに自動化用シングルテナントアプリ |
|---|---|---|
| 手動が必要な場所 | 新テナントでマルチテナントアプリに対する テナント全体の管理者同意(1 回) | テナント作成直後に、 初期管理者アカウントでのサインイン(1 回) |
| その後の構成 | マルチテナントアプリのアプリケーション許可で Graph / 管理 API をヘッドレス実行 | 各テナント内の自動化アプリ(シングルテナント)を使って Graph を呼び出し |
| 利点 | マルチテナントアプリ 1 つで全テナントを管理できる。 スクリプトはシンプル。 | マルチテナントの admin consent を避けられる。 テナント内完結の権限モデル。 |
| 注意点 | 顧客側の admin consent プロセスの設計が必要。 (URL 配布・承認フローなど) | 初期管理者アカウントの保管・ローテーションが重要。 (Key Vault など) |
| 向いているケース | ISV / SaaS ベンダーで、顧客側担当者が admin consent を実行できる体制がある。 | 自社グループ内の複数テナントを一括管理するケースなど、 初期管理者を自分で持てる環境。 |
以降では、この 2 パターンに沿って、実装時のポイントを見ていきます。
方式 A:ホステナントのマルチテナントアプリ+管理者同意 1 回
もっとも扱いやすいのは、ホステナント側に 1 つマルチテナントアプリを用意し、これに必要な Graph アプリケーション許可を付けておくパターンです。
ステップ 1:CIAM テナントを API で作成する
CIAM テナントは Azure Resource Manager の Microsoft.AzureActiveDirectory/ciamDirectories リソースとして作成します。
Bicep での例(イメージ)は次のとおりです。
resource ciamTenant 'Microsoft.AzureActiveDirectory/ciamDirectories@2023-05-17-preview' = {
name: 'my-customer-ciam'
location: 'Europe' // US / Europe / Asia Pacific / Australia など
sku: {
name: 'Standard'
tier: 'A0'
}
properties: {
createTenantProperties: {
countryCode: 'JP'
displayName: 'Contoso Customer CIAM'
}
}
}
ポイントは以下の通りです。
locationやskuはドキュメントに定義された値のみ指定可能。- デプロイ完了後、
tenantIdが払い出されるが、すぐに Graph API を叩くと 404 や 401 になることがある(伝搬待ち)。 - そのため、ポーリング+指数バックオフ(retry-with-backoff) を必ず実装する。
疑似コードで書くとこんなイメージです。
for (retry = 0; retry <= maxRetry; retry++) {
try {
// 新テナントの Graph エンドポイントに軽い GET を投げる
GET https://graph.microsoft.com/v1.0/organization
// 成功したらループを抜ける
break;
} catch (e) {
wait(2^retry * baseDelay);
}
}
ステップ 2:新テナントでの admin consent(ここだけ手動)
CIAM テナントが生成され、ある程度伝搬が完了したら、次は マルチテナントアプリに対するテナント全体の管理者同意を行います。
admin consent エンドポイントは次のような URL 形式です。
https://login.microsoftonline.com/{newTenantId}/v2.0/adminconsent
?client_id={multiTenantAppClientId}
&redirect_uri={URL エンコードしたリダイレクト URI}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&state={任意の CSRF 対策用値}
この URL に、次のロールのいずれかを持つユーザーでサインインしてもらう必要があります。
- Global Administrator
- Privileged Role Administrator
- Cloud Application Administrator など
運用上は、次のようなフローにするのがおすすめです。
- 自動化パイプラインが CIAM テナントを作成。
- テナント ID と admin consent URL を生成し、社内ワークフロー(Teams / メール / 承認システム)で対象の管理者に通知。
- 管理者がブラウザで URL を開き、要求されている Graph 権限を確認して「承諾」。
- 成功後は指定した
redirect_uriに戻ってくるので、そこで状態を記録。
このワークフローをきちんと整えておけば、手動ステップは 「URL を開いて承諾ボタンを押す」だけにできます。
ステップ 3:Graph API でアプリ登録/ユーザーフローをヘッドレス構成
admin consent が完了すると、新テナントにマルチテナントアプリのサービス プリンシパルが作成され、そのアプリケーション許可に基づいて Graph を アプリケーション トークン(client_credentials フロー)で呼び出せるようになります。
トークン取得(client_credentials)
MSAL / 任意の HTTP クライアントから、次のようなリクエストでトークンを取得します。
POST https://login.microsoftonline.com/{newTenantId}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={multiTenantAppClientId}
client_secret={clientSecret or clientAssertion}
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
grant_type=client_credentials
取得したアクセストークンを Authorization: Bearer {token} として以下の処理を実行します。
アプリ登録の自動作成
顧客向けアプリ(フロントエンドなど)を CIAM テナント側に作成する場合は、Graph の /applications / /servicePrincipals エンドポイントを利用します。
POST https://graph.microsoft.com/v1.0/applications
Content-Type: application/json
{
"displayName": "Contoso Customer Portal",
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"web": {
"redirectUris": [
"https://app.contoso.com/auth/callback"
]
},
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000", // Microsoft Graph
"resourceAccess": [
{
"id": "some-app-role-guid",
"type": "Scope"
}
]
}
]
}
その後、/servicePrincipals に POST してサービス プリンシパルを作成し、必要に応じて他アプリへの appRoleAssignments を設定していきます。
ユーザーフローの作成・更新(External ID)
Entra External ID のユーザーフローは、Graph では主に /identity/authenticationEventsFlows というリソースとして扱われます。
GET /beta/identity/authenticationEventsFlowsでユーザーフローの一覧を取得。- アプリ ID を指定して関連付いたユーザーフローだけを絞り込む例も公式ドキュメントにあります。
- サインアップの無効化などは
PATCH /beta/identity/authenticationEventsFlows/{flow-id}で行います。
サインアップを無効化する例:
PATCH https://graph.microsoft.com/beta/identity/authenticationEventsFlows/{user-flow-id}
Content-Type: application/json
{
"@odata.type": "#microsoft.graph.externalUsersSelfServiceSignUpEventsFlow",
"onInteractiveAuthFlowStart": {
"@odata.type": "#microsoft.graph.onInteractiveAuthFlowStartExternalUsersSelfServiceSignUp",
"isSignUpAllowed": false
}
}
なお、Azure AD B2C 時代の /identity/b2cUserFlows も引き続き存在しますが、External ID(Azure AD for customers)向けのシナリオでは authenticationEventsFlows と関連ドキュメントを優先的に参照した方が安全です。
Identity Provider や属性の自動構成
External ID では、ユーザーフロー内で利用する ID プロバイダーやユーザー属性も Graph から操作できます。
- Identity Providers:
/identity/identityProviders - ユーザーフロー属性:
/identity/userFlowAttributes - カスタム認証拡張(API コネクタ相当): custom authentication extensions / event handler リソース
これらを組み合わせることで、
- Google / Facebook / OIDC などのソーシャル ID プロバイダーを登録
- サインアップ時に収集する属性(住所・会員番号など)を追加
- サインアップ中に外部 API(Logic Apps / Functions)を呼び出してワークフローを実行
といった高度なカスタマイズを すべてスクリプト化できます。
方式 A を成立させるための権限設計
マルチテナントアプリには、次のような アプリケーション許可を付与するケースが多いです。
| 用途 | 代表的な Graph アプリケーション許可 |
|---|---|
| ディレクトリ全体の構成変更 | Directory.ReadWrite.All |
| アプリ登録・サービス プリンシパル管理 | Application.ReadWrite.All |
| ユーザーフロー(External ID)の管理 | IdentityUserFlow.ReadWrite.All など(プレビューのためドキュメントを随時確認) |
これらは 非常に強い権限であるため、
- ホステナント側のロール(例:Global Administrator)が admin consent を行う前に、最小権限設計になっているかを確認する
- 必要に応じて 専用の自動化アプリを用意し、人間が使うアプリとは切り離す
- アプリのシークレットではなく 証明書認証を第一候補とする
といったセキュリティベストプラクティスを守ることが重要です。
方式 B:各 CIAM テナント内に「自動化専用アプリ」を作る
もう一つのパターンは、マルチテナントアプリの admin consent を避ける代わりに、各 CIAM テナントに「自動化専用のシングルテナントアプリ」をセットアップする方式です。
ステップ 1:CIAM テナント作成(方式 A と同じ)
テナント作成の部分は方式 A と同じく、Microsoft.AzureActiveDirectory/ciamDirectories を用いて自動化します。
ステップ 2:初期管理者アカウントでのサインイン
方式 B のポイントは、
- CIAM テナント作成と同時に、そのテナントの Global Administrator 相当の初期アカウントを発行しておく
- このアカウントの 資格情報(理想的には FIDO2 / PIM + 事前委任など)を安全に保管しておき、CI/CD から利用する
という前提を置くことです。
実際の自動化では、
- 初期管理者アカウントで一度だけインタラクティブサインインし、デバイスコード フロー+長期リフレッシュトークンを取得して Key Vault に格納する
- あるいは、初期管理者が テナント内に自動化用アプリを作成し、Graph アプリケーション許可に admin consent を付ける
といった形で「最初の一歩」だけは人が実行します。
ステップ 3:CIAM テナント内に自動化用アプリを作成
初期管理者の権限を用いて、
POST /applicationsで「自動化用アプリ」を作成POST /servicePrincipalsで同アプリのサービス プリンシパルを作成- Graph に対する
Application.ReadWrite.Allなど必要なアプリケーション許可をアプリに付与し、自テナント内で admin consent を完了
これで、以降は 自動化アプリのクレデンシャル(クライアント資格情報フロー)だけで CIAM テナントをフル制御できるようになります。
ユーザーフローや ID プロバイダー、カスタム属性などの構成は、方式 A と同様に authenticationEventsFlows や identity/userFlowAttributes などの Graph API を用いてヘッドレスで自動化可能です。
方式 B を採用する際の注意点
- 初期管理者アカウントは 最も重要な秘密情報なので、パスワードベースではなく PIM / 条件付きアクセスなどを組み合わせて漏洩リスクを抑える。
- CIAM テナントの数が多い場合、各テナントにアプリが 1 つ増えるため、インベントリ管理が多少複雑になる。
- グループ会社など「自分たちで全テナントの管理者権限を保持できる」ケースには向くが、外部顧客テナントにはやや重い(顧客の管理者に初期ログインを依頼するなら、方式 A と変わらない)。
ユーザーフロー自動化の実務ポイント
どちらの方式を採用しても、最終的には「Graph でユーザーフローをどういじるか」が実務の肝になります。
ユーザーフロー ID の取得
External ID のユーザーフロー ID はポータルからは直接見えないことが多く、Graph で次のように取得します。
- アプリ ID から関連ユーザーフローを検索
GET /beta/identity/authenticationEventsFlowsに対してフィルターを使うか、レスポンスから対象アプリ ID をもつエントリを探します。 - レスポンスの
idがユーザーフロー ID になるので、これを以降の PATCH / DELETE などで利用。
サインアップ/サインイン設定のテンプレート化
実務上は、
- 「メール+パスワード」か「メール+ワンタイムパスコード」か
- MFA の有無・種類(SMS / E メール OTP)
- サインアップの可否(
isSignUpAllowed)
などを JSON テンプレートとして作っておき、CIAM テナントごとに差分(ブランド名・リダイレクト URI・クレーム名など)を差し込む形にするのが効率的です。
カスタム認証拡張(API コネクタ)の自動配線
External ID では、ユーザーフローの途中で外部 API(Azure Functions / Logic Apps 等)を呼び出す custom authentication extensions を設定できます。
- サインアップ時の属性入力後に社内 CRM と突合する
- 不正アクセス検知サービスと連携してリスクベース認証を行う
- ユーザー作成完了後に別システムのアカウントを自動発行する
といった処理を、すべて HTTP ベースのイベント駆動で差し込めます。これも Graph API からリソースとして管理できるため、
- API コネクタ(custom authentication extension)を Graph で登録
- ユーザーフローに対して「このイベントのタイミングでこの拡張を呼ぶ」設定を追加
という 2 ステップをスクリプト化しておくと、テナント横展開が非常に楽になります。
運用で絶対に押さえておきたいポイント
1. リトライと冪等性
- CIAM テナント作成直後は、Graph から見るとディレクトリが「半完成状態」になっていることがある。
- よくある症状は、
/organizationが 404 / 401 を返す、/identity/authenticationEventsFlowsが空を返す、など。 - これを前提に、全 API 呼び出しにリトライ+バックオフを必ず実装し、「既に存在する場合は取得に切り替える」冪等ロジックを入れておく。
2. シークレット/証明書のライフサイクル
- 自動化アプリのクライアントシークレットは極力避け、証明書認証+ Azure Key Vault を組み合わせる。
- どうしてもシークレットを使う場合は、有効期限の短いものを使い、ローテーション用のバッチを CI/CD に組み込む。
- Key Vault へのアクセスも マネージド ID を使って人手の秘密情報を減らす。
3. ログと監査
- admin consent やアプリケーション許可の更新は、監査ログの取得と保管を必須にする。
- どのパイプラインが、どのテナントに対して、どの権限をいつ付与したのかを追跡できるようにする。
- 異常系(想定外の 4xx / 5xx)を検出したら 運用チームに通知する仕組みを入れておく。
4. テンプレート化とバージョン管理
- ユーザーフロー設定、ID プロバイダー設定、カスタム属性、API コネクタ定義などを JSON / Bicep / Terraform でテンプレート化。
- Git リポジトリでバージョン管理し、Pull Request ベースで設定変更をレビュー可能にする。
- 「v1 ユーザーフロー」「v2 ユーザーフロー」といった形で段階的ロールアウトもやりやすくなる。
「サイレントログイン API」の幻想にハマらないために
最後に、よくある質問に対して、この記事の内容を踏まえつつ要点をまとめておきます。
Q1:ログイン不要で新テナントに“サイレント”で入れませんか?
A:できません。
新テナントに対してトークンを発行するには、
- そのテナントのユーザー(管理者)がサインインする
- そのテナントで admin consent されたサービス プリンシパルとしてトークンを取得する
のどちらかが必須です。どちらのケースでも、どこかのタイミングで「そのテナントが信頼する主体」を確立するための人間の操作が要る点は変わりません。
Q2:じゃあ完全自動化は絶対に無理?
A:設計上、100%の完全自動化は無理ですが、この記事で紹介したように 「1 テナントあたり 1 回の人間の承認」まで縮退することはできます。
- 方式 A:マルチテナントアプリへの admin consent を 1 回だけ実行し、その後は Graph で全自動化
- 方式 B:初期管理者で CIAM テナント内に自動化アプリを配置し、その後はそのアプリのアプリケーション許可で全自動化
Q3:どちらの方式を選ぶのがよい?
- 外部顧客テナントが中心なら方式 A:顧客側の管理者に admin consent を 1 回だけ依頼し、それ以外をすべて自動化する。
- 自社グループや社内用 CIAM テナントなら方式 B:自分たちで初期管理者を握れるので、テナント内完結で構成できる。
どちらを選んだとしても、「信頼を与える最初のステップだけは人間が行う」という前提を崩すことはできません。
実務で使えるチェックリスト
最後に、Entra External ID(CIAM)のテナント増設~ユーザーフロー構成を自動化する際に、最低限押さえておきたいチェックリストをまとめます。
- [ ] CIAM テナント作成の自動化
Microsoft.AzureActiveDirectory/ciamDirectoriesを Bicep / Terraform / REST などで作成- 作成後の伝搬完了を待つポーリング&バックオフを実装
- [ ] 方式 A or 方式 B の選択
- 方式 A:マルチテナントアプリ+ admin consent(顧客側管理者に 1 回実行してもらうワークフロー設計)
- 方式 B:初期管理者で CIAM テナント内自動化アプリを作り、以降はそのアプリで Graph を実行
- [ ] Graph アプリケーション許可の設計
Directory.ReadWrite.AllやApplication.ReadWrite.All、IdentityUserFlow.ReadWrite.Allなど、最小限のアプリケーション許可を付与- admin consent 実行者のロール(Global Admin 等)を明確化
- [ ] ユーザーフローのテンプレート化
/identity/authenticationEventsFlowsを用いてユーザーフローを作成/取得/更新isSignUpAllowedや ID プロバイダー、カスタム属性、API コネクタを JSON テンプレートとして管理
- [ ] シークレット/証明書・Key Vault 設計
- [ ] 監査ログ・アラート・インベントリ管理
- [ ] Git ベースのテンプレート管理と PR レビュー
以上を押さえておけば、「Entra External ID テナントを顧客ごとに自動で量産し、ユーザーフローまでセットアップする」ための基盤は十分に整います。最後にもう一度だけまとめると、
- テナント全体の管理者同意だけは、人間による操作が必須
- しかし、その 1 回さえワークフロー化してしまえば、それ以外の構成は Graph / ARM / Terraform で完全ヘッドレスに自動化可能
というのが、Entra External ID(CIAM)自動化の現実解です。

コメント