Entra External IDでローカルサインアップを無効化しつつ外部IdPから自動ユーザー作成を実現する方法と限界(Azure AD B2Cとの違いも解説)

Azure AD B2C から Microsoft Entra External ID への移行を検討すると、「ローカルのメール/パスワードによるサインアップだけ禁止しつつ、外部 IdP(OpenID Connect など)で認証されたユーザーは初回ログイン時に自動作成したい」という要件でつまずきがちです。本記事では、2025年11月時点の仕様を踏まえて「できること/できないこと」を整理し、実務レベルで取り得る回避策と設計の考え方を詳しく解説します。

目次

シナリオ整理:やりたいことと現状のギャップ

まずは要件と現状を整理します。

項目要件現状(Entra External ID)
ローカル アカウント新規登録メール+パスワードによる新規サインアップは禁止したいユーザーフローの isSignUpAllowed を false にすればサインアップ UI は消せる
外部 IdP ユーザーの初回ログイン初回ログイン時にテナント内ユーザーを自動作成したい(B2C と同じ動き)isSignUpAllowed: false にすると、IdP 経由の初回ログインでもユーザー自動作成が行われず、
AADSTS50020 エラーで弾かれる
Azure AD B2C との違いローカル サインアップのみ禁止し、IdP からの自動作成は許可B2C はカスタムポリシー等で「ローカル サインアップだけ禁止」が可能だが、External ID には同等のスイッチが現在存在しない

ポイントは、Entra External ID のサインアップ制御が「ローカル/外部 IdP」を個別に ON/OFF するのではなく、「ユーザー作成を伴うサインアップそのもの」を丸ごと制御しているところです。

Entra External ID のサインアップ制御の仕組み

ユーザーフローと externalUsersSelfServiceSignUpEventsFlow

Entra External ID(外部テナント / Customers)は、サインアップ/サインインの体験を externalUsersSelfServiceSignUpEventsFlow というマルチイベントポリシーとして管理します。Microsoft Graph 上では /identity/authenticationEventsFlows にぶら下がるリソースで、次のようなイベントを持ちます。

  • onInteractiveAuthFlowStart … 画面フロー開始時(サインアップを含めるかどうか)
  • onAuthenticationMethodLoadStart … どの IdP(EmailPassword, Google, Facebook, OIDC など)を表示するか
  • onAttributeCollection … サインアップ時に収集する属性
  • onUserCreateStart … 作成するユーザーの種別(member / guest)など

このうち、今回のテーマに直接関係するのが onInteractiveAuthFlowStart の isSignUpAllowed プロパティです。

isSignUpAllowed が担っている役割

onInteractiveAuthFlowStartExternalUsersSelfServiceSignUp のドキュメントでは、isSignUpAllowed を次のように説明しています。

  • 型: Boolean
  • 意味: 「サインアップ(アカウント作成)をサインイン体験に含めるかどうか」
  • 既定値: false(サインインのみ)

実際にサインアップを無効化する手順は、公式ドキュメントのとおり以下のように Graph API でフローを更新します。

PATCH https://graph.microsoft.com/v1.0/identity/authenticationEventsFlows/{user-flow-id}
Content-Type: application/json

{
  "@odata.type": "#microsoft.graph.externalUsersSelfServiceSignUpEventsFlow",
  "onInteractiveAuthFlowStart": {
    "@odata.type": "#microsoft.graph.onInteractiveAuthFlowStartExternalUsersSelfServiceSignUp",
    "isSignUpAllowed": false
  }
}

つまり isSignUpAllowed = false にするということは、「このユーザーフローではユーザー作成を伴うサインアップ体験そのものを出さない」という宣言になります。

設定値ごとの実際の挙動

シナリオisSignUpAllowed: trueisSignUpAllowed: false
既存ローカルユーザーのサインインサインイン可能サインイン可能
新規ローカル サインアップ「No account? Create one」等から作成可能サインアップ UI が出ず、作成不可
既存 IdP ユーザーのサインインサインイン可能サインイン可能
IdP ユーザーの初回サインイン(テナントに存在しない)ユーザーが自動作成されてサインイン(=サインアップ扱い)ユーザーが作成されず、AADSTS50020 で失敗

ここが重要なポイントで、IdP からの「自動ユーザー作成」も内部的にはサインアップの一種として扱われるため、isSignUpAllowed: false にするとローカルだけでなく IdP からの初回作成もまとめて止まってしまいます。

Microsoft 公式回答:現時点では「設定だけで実現」は不可能

この挙動については、まさに同じ質問が Microsoft Q&A に上がっており、Microsoft のサポート エンジニアから次のような回答が出ています。

  • 質問内容:
    • Entra External ID で isSignUpAllowed = false にすると、
      カスタム OIDC IdP からの初回ログインでもユーザー自動作成が行われず AADSTS50020 になる
    • Azure AD B2C では「ローカル サインアップ禁止+IdP 初回ログインで自動ユーザー作成」が可能だが、External ID でも同様の設定はあるか?
  • Microsoft 回答(要約):
    • 現時点では、サインアップ無効化時に IdP からの自動ユーザー作成を許可する機能は存在しない
    • isSignUpAllowed を false にすると、ローカルサインアップだけでなく IdP 経由の自動作成も止まるのは仕様
    • この構成を実現するには、何らかの外部オーケストレーション(Graph API など)でユーザー作成をハンドリングする必要がある
    • 要望は Azure Feedback ポータルから投稿してほしい

つまり、「ローカル サインアップだけ止めて、IdP からの自動ユーザー作成だけ許可」することは 2025年11月時点では公式設定だけでは不可能と明言されています。

Azure AD B2C と Entra External ID の違い

同じことが B2C ではできていたのに…という気持ちになるので、両者の差をざっくり整理します。

観点Azure AD B2CEntra External ID(Customers)
ポリシー モデルカスタムポリシー(TrustFrameworkPolicy)で
柔軟なユーザージャーニーを定義
authenticationEventsFlow ベースの
マルチイベントポリシー
サインアップ制御の粒度技術プロファイルを組み合わせて、
IdP ごとにサインアップ可否を細かく制御可能
isSignUpAllowed で「サインアップ全体」をまとめて ON/OFF
UI カスタマイズ完全なカスタム HTML + JS で構築可能ブランド設定+カスタム CSS による見た目調整が中心。
完全なカスタム HTML は現時点では不可。
ローカルのみサインアップ禁止カスタムポリシーで実現可能公式には不可。UI や外部ロジックでの「疑似的な表現」は可能

設計思想として、External ID は「XML ベースの複雑なカスタムポリシーから脱却し、イベントドリブンでシンプルにする」方向に振っている分、細かい挙動を調整する余地が現状は少ないと言えます。

結論の整理:何が「できない」のか

2025年11月時点の結論をはっきり書くと、次のようになります。

  • External ID 単体の設定だけでは、以下の状態を両立できない:
    • ローカル アカウントによる新規サインアップを禁止
    • IdP からの初回ログイン時にユーザーを自動作成
  • isSignUpAllowed: false にした瞬間、「ユーザー作成を伴うすべてのフロー」が止まるため、IdP からの自動作成も同時に無効化される
  • したがって、現状は
    • サインアップを許可したまま UI 側でローカル サインアップを見せないようにするか、
    • サインアップを無効化し、その代わりに Graph API 等で「事前/即時プロビジョニング」を行う
    のどちらか(または組み合わせ)が現実的な落としどころになります。

回避策パターン①:サインアップ許可のまま UI からローカル サインアップを隠す

最も手軽なアプローチは、isSignUpAllowed を true のままにしつつ、サインアップ UI(特にローカル アカウント向け)を CSS で非表示にする運用です。

基本アイデア

  • ユーザーフロー側:
    • isSignUpAllowed: true → サインアップは許可(IdP からの自動作成も動く)
    • onAuthenticationMethodLoadStart で IdP と EmailPassword を両方有効化
  • ブランディング側:
    • Company Branding の「カスタム CSS」機能を使って、サインアップ用リンクやボタンを非表示にする

External ID のブランド設定では、サインイン/サインアップ画面に対して任意の CSS ファイルを適用できます。これを利用して、「No account? Create one」やローカル サインアップ用のボタンを非表示にします。

設定ステップ例

  1. Microsoft Entra 管理センターで外部テナントに切り替える
  2. Entra ID > Custom Branding を開き、「Default sign-in」タブで Edit をクリック
  3. Layout タブで「Custom CSS」をアップロードできる欄があるので、自前の CSS ファイルを指定
  4. CSS ファイル側で、ブラウザーの開発者ツールで確認したクラス/属性を使って対象要素を非表示にする

CSS の具体的なセレクタは UI のバージョンによって変わり得るためここでは例示に留めますが、イメージは次のような形です(あくまで概念的な例)。

/* 「No account? Create one」リンクを隠す(実際のクラス名は要確認) */
a[data-test-id="signup-link"],
a[href*="signup"] {
  display: none !important;
}

/* ローカル サインアップのボタンだけ隠し、IdP ボタンは残す */
div.local-account-signup {
  display: none !important;
}

メリット・デメリット

観点メリットデメリット
実装コストポータル操作+ CSS だけなので比較的軽いCSS セレクタの調査・検証が必要
IdP 自動作成isSignUpAllowed: true のままなので、初回ログイン時の自動作成がそのまま動くサインアップ自体は内側では有効のまま
ローカル サインアップの抑止通常のユーザーには「サインアップの入り口」がほぼ見えなくなるCSS 無効化・直接 URL などで完全に防ぐことはできない UI の仕様変更で CSS が効かなくなるリスク
セキュリティ「うっかりローカルで作られる」事故は大きく減らせるセキュリティ境界としては不十分(あくまで見た目の制御)

「管理者が勝手にローカル サインアップさせてしまうのを防ぎたい」「ほとんどのユーザーは IdP しか使わない」という前提なら、まず検討する価値がある簡易対策です。

回避策パターン②:IdP 側承認 → Graph API で事前プロビジョニング

より厳密に制御したい場合は、サインアップ自体を無効化し、その代わりに管理側でユーザーを事前作成するという設計が有力です。

基本アイデア

  1. IdP 側で「このユーザーは自社アプリにアクセスしてよい」と判断されたユーザーを一覧化する
    • IdP 管理者の手動承認
    • IdP からの定期エクスポート(CSV / API)
    • 他システムからのユーザー登録申請ワークフロー など
  2. その一覧を元に、Microsoft Graph API で External ID テナントにユーザーを事前作成する
  3. ユーザーは初回アクセス時、既にテナントに存在しているため、isSignUpAllowed: false のままでもサインインのみで通せる

事前プロビジョニングには大きく 2 つのパターンがあります。

  • B2B 招待(POST /invitations) を使ってゲストユーザーとして招待する
  • 通常のユーザー(member)を直接作成する(CIAM テナントとして顧客を「会員ユーザー」として扱うパターン)

Graph /invitations を使う例(B2B 的な使い方)

B2B コラボレーションとして扱う場合は、招待 API を使うのがシンプルです。

POST https://graph.microsoft.com/v1.0/invitations
Content-Type: application/json

{
  "invitedUserEmailAddress": "[email protected]",
  "inviteRedirectUrl": "https://your-app.example.com/",
  "sendInvitationMessage": false
}

これにより、対象のメールアドレスに紐づく外部ユーザーがテナントに追加されます。実運用では PowerShell や Azure Functions から CSV を読み込んで一括実行する、などのパターンが多いでしょう。

CIAM 的に「会員ユーザー」として作成する例

Customers シナリオでは、外部ユーザーを userType: member として扱うことも一般的です。その場合は、POST /users でユーザーを作成し、IdP 側の識別子ときちんと紐付くように属性(identities など)をセットする設計になります。

この部分はシステム設計によってかなり違いが出るため詳細 JSON は省略しますが、考え方としては次の通りです。

  • IdP から提供される識別子(sub、メールアドレス、tenantId など)を決めておく
  • External ID テナント側のユーザーに、その識別子を一意キーとして保存する属性を用意する
    • カスタム属性
    • signInNames / identities 相当の仕組み など
  • サインイン時にその識別子でユーザーが引けるように、ユーザーフローと合わせて設計する

ワークフローの例

典型的な実装フローをテキスト図で表すと、次のようになります。

  1. 顧客企業の IdP 管理者が自社ユーザーを承認
  2. IdP から承認済みユーザー一覧を毎晩エクスポート(CSV / API)
  3. Azure Functions(または Logic Apps)が一覧を読み取り、まだ存在しないユーザーだけを Graph API で作成
  4. ユーザーには「アカウントが有効化されました」という通知を別途送信
  5. ユーザーは External ID 経由でサインイン → 既にユーザーが存在するため、isSignUpAllowed: false でもエラーにならない

メリット・デメリット

観点メリットデメリット
制御性誰がいつテナントに作成されるかを管理者側で 100% 制御できる承認プロセスや連携バッチの設計・運用が必要
セキュリティ / コンプライアンス「承認されたユーザーだけが存在する」状態を保証しやすいIdP 側のロール・グループとの同期設計も考慮が必要
ユーザー体験「招待メール到着後にログイン」など、オンボーディングをデザインしやすい完全な「初回ログインだけで即利用」と比べると一手間増える

回避策パターン③:AADSTS50020 失敗をトリガーに即時プロビジョニング

「どうしても ユーザーによる事前申請ナシで初回ログインから自動作成したい」場合は、サインイン失敗ログをトリガーにユーザーを即時作成するアーキテクチャも考えられます。

基本アイデア

  • ユーザーが IdP で認証 → External ID ユーザーフローにリダイレクト
  • ユーザーがテナントに存在しない & isSignUpAllowed: false のため、AADSTS50020 エラーで失敗
  • サインインログに AADSTS50020 が記録される(「User account does not exist in tenant」)
  • このログを Azure Monitor / Log Analytics / Event Hub 経由でリアルタイム検知し、Graph API でユーザーを作成
  • ユーザーに「アカウント作成完了。もう一度ログインしてください」と案内

実装ステップ(概要)

  1. External ID テナントのサインインログに診断設定を有効化し、Log Analytics ワークスペース(または Event Hub)に送信
  2. Kusto クエリで AADSTS50020 のレコードだけを抽出するクエリを用意
    • 例(イメージ):SigninLogs | where ResultType == 50020 and AppId == "your-app-id"
  3. Logic Apps または Azure Functions で、該当ログをトリガーに Graph API を呼び出しユーザーを作成
  4. ユーザー作成後に、通知メール・Webhook などで「再ログインしてください」と案内

この方式は、いわば「1 回目のログイン失敗をきっかけにサーバー側で即座にユーザーを作り、2 回目以降は成功させる」というリカバリ フローです。

このパターンを採用する際の注意点

  • リアルタイム性:
    • サインインログ → 関数起動 → ユーザー作成 の間に多少の遅延が出るため、ユーザーには「数十秒〜数分後に再ログインしてください」と説明が必要
  • 二重作成防止:
    • 再試行やエラー時に同じユーザーを複数作らないよう、ユニークキー(メールアドレスなど)で存在チェックを行うロジックが必須
  • ログのノイズ:
    • 本当にアクセスを許可したくないユーザーも AADSTS50020 になるため、「どのドメイン/IdP から来たユーザーだけを自動作成してよいか」を明確にフィルタリングする必要があります

運用難易度は高いものの、「External ID の機能で足りない部分をログベースのオートプロビジョニングで補う」という考え方としては現実的な選択肢です。

回避策パターン④:B2C と External ID の役割分担・段階移行

Azure AD B2C そのものは新規テナント作成が停止されたものの、既存テナントは 2030 年 5 月までサポートされると案内されています。

そのため、次のような割り切りも選択肢になります。

  • 自動ユーザー作成ロジックを B2C 側に残す
    • 既に B2C カスタムポリシーで「ローカル禁止+IdP 自動作成」パターンが完成しているなら、短期的にはそのまま運用継続
  • 新規サービスや要件がシンプルなものから External ID に寄せる
    • B2C にある高度なカスタマイズが不要なアプリは、External ID に移行して管理コストを下げる
  • 将来、External ID に B2C 相当の機能が入ったタイミングで再検討
    • External ID のロードマップ上で、ユーザーライフサイクル管理や自動ユーザー作成の強化が進む可能性は高い

もちろん、中長期的には External ID へのフル移行が求められるため、「どこまでを今 B2C に残し、どこから External ID に寄せるか」をシステム全体で設計することが重要です。

UI カスタマイズでできること・できないこと

ローカル サインアップを「完全に」塞ぐことはできないものの、External ID でも UI 側である程度の誘導は可能です。

できること(2025年11月時点)

  • 背景画像・色・レイアウト(ヘッダー/フッター)変更
  • ロゴ・プライバシーリンク・利用規約リンクの変更
  • サインインフォームの文言(ヒントテキスト、注意書き)の変更
  • サインイン/サインアップ画面のテキストを JSON ベースでカスタマイズ
  • カスタム CSS の適用(色・フォント・配置・一部要素の非表示など)

できない/注意が必要なこと

  • 完全なカスタム HTML に差し替える(B2C のようにフルスクラッチで UI を作る)ことは現時点では不可
  • JavaScript を自由に埋め込んで任意のロジックを実行することも不可
  • CSS による非表示はあくまで「見せない」だけであり、機能そのものを無効化するわけではない

このため、「UI でローカル サインアップの導線を極力隠す」「注意書きで『サインアップは IdP からのみ受け付けます』と明記する」といったソフトな抑止と、先述の Graph API ベースのプロビジョニングを組み合わせるのが現実解になりやすいです。

設計時にチェックしたいポイント一覧

ここまでの内容を踏まえ、「ローカル サインアップ無効+IdP 自動作成に近い体験」を External ID 上で実現する際のチェックリストをまとめます。

カテゴリチェックポイント
要件整理本当に「ローカル サインアップ完全禁止」が必要か? 既存ローカルユーザーのサインインはどこまで許容するか? IdP の種類(Entra ID / 他社 IdP / ソーシャル)の組み合わせ
ユーザーフロー設計どのフローで isSignUpAllowed: true / false にするか アプリごとにユーザーフローを分ける必要があるか IdP ごとに別フローを用意した方が管理しやすいか
IdP 連携IdP から取得できるクレーム(メール、tenantId など)を確認 External ID 側でどの属性を一意キーとして扱うかを明確化
プロビジョニング方式事前プロビジョニングか、ログトリガー型か、それとも併用か Graph API に必要な権限(User.ReadWrite.All / User.Invite.All など) 失敗時のリトライ戦略・監視方法
ユーザー体験初回アクセス時の流れ(どこで「アカウントがまだありません」と伝えるか) 再ログインが必要な場合、その案内をどう行うか
運用とガバナンス外部ユーザーの棚卸し(未利用アカウントの削除) ログ監査(不審なサインアップ試行の検知) IdP 側の退職者・無効ユーザーと External ID ユーザーの連動

今後のロードマップとフィードバックの出し方

External ID は 2024 年に GA したばかりの新しいサービスであり、今も機能追加が続いています。とはいえ、「ローカル サインアップを無効化しつつ、IdP 自動作成だけ許可する」ような細かい制御はまだ提供されていません。

Microsoft 側も、B2C からの移行ニーズや顧客要件を踏まえて機能追加の優先度を決めているため、実際にこの機能が必要な場合は次のような情報を添えてフィードバック ポータルに要望を投げると効果的です。

  • どのようなビジネス要件か(例:SaaS マルチテナント、複数顧客の IdP 連携など)
  • 対象ユーザー数(例:数万アカウント規模)
  • 現行 B2C でどのようなカスタムポリシーを組んでいるかの概要
  • External ID で実現しようとしている構成図(簡易なもので可)
  • いつまでに必要か(B2C 廃止までに移行を完了したい、など)

また、Microsoft Q&A やコミュニティで類似の質問が上がっている場合は、それに「同じ課題を持っている」という形でコメント/投票するのも有効です。

まとめ

  • 結論:
    • 2025年11月時点、Entra External ID には「ローカル サインアップだけ禁止しつつ、IdP からの初回ログインでユーザー自動作成を許可する」ための公式スイッチはありません。
    • isSignUpAllowed: false にすると、ローカル/IdP 問わずユーザー作成を伴うすべてのフローが止まるため、AADSTS50020 が発生します。
  • 現実的な回避策:
    • isSignUpAllowed: true のまま、Company Branding のカスタム CSS でローカル サインアップの UI を非表示にする
    • IdP 側承認フロー+ Graph API による事前プロビジョニング(/invitations や /users)を組み込む
    • どうしても初回ログインで自動作成したい場合は、AADSTS50020 のサインインログをトリガーにユーザーを即時作成するフローを構築する
  • 設計方針:
    • UI 側の工夫とサーバーサイドのプロビジョニング(Graph API)を組み合わせて、「ユーザーに見せたい体験」と「セキュリティ・運用要件」のバランスを取る
    • B2C で実現していた複雑なカスタムポリシーは、External ID では「複数のユーザーフロー+外部オーケストレーション」で置き換える前提で考える
    • 将来的な製品改善を見据えつつ、今必要な要件については Azure Feedback 等で積極的に声を上げる

「ローカル サインアップを無効化しつつ、カスタム IdP からのユーザー自動作成を許可したい」という要件は、多くの B2C ユーザーが External ID への移行で直面するテーマです。本記事の内容をベースに、自社のセキュリティ要件・運用体制に最もフィットするパターンを検討してみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次