Microsoft Entra ID でシングルテナント アプリをマルチテナントに変換する

サービスとしてのソフトウェア (SaaS) アプリケーションを多数の組織に提供する場合は、アプリケーションをマルチテナントに変換することで、すべての Microsoft Entra テナントからのサインインを受け入れるように構成することができます。 すべての Microsoft Entra テナントのユーザーは、アプリケーションで自分のアカウントを使用することに同意すれば、そのアプリケーションにサインインできるようになります。

独自のアカウント システムを持つ既存のアプリ (または他のクラウド プロバイダーからのその他のサインイン) の場合は、OAuth2、OpenID Connect、または SAML を使用してサインイン コードを追加し、アプリケーションに [Microsoft アカウントでサインイン] ボタンを配置する必要があります。

このハウツー ガイドでは、シングル テナント アプリを Microsoft Entra マルチテナント アプリに変換するために必要な、次の 4 つの手順を実行します。

  1. アプリケーション登録をマルチテナントに更新する
  2. コードを更新して、要求を /common エンドポイントに送信するようにします
  3. 複数の issuer 値を処理するようにコードを更新する
  4. ユーザーおよび管理者の同意について理解し、コードに適切な変更を加える

いずれかのサンプルの使用を試す場合は、「Azure AD と OpenID Connect を使用して Microsoft Graph を呼び出すマルチテナント SaaS Web アプリケーションを構築する」を参照してください

前提条件

登録をマルチテナントに更新する

既定では、Microsoft Entra ID での Web アプリケーション/API 登録は、作成時点でシングルテナントです。 登録をマルチテナントにするには、Microsoft Entra 管理センターにログインし、更新するアプリ登録を選択します。 アプリ登録を開いた状態で、[認証] ペインを選択し、[サポートされるアカウントの種類] セクションに移動します。 設定を [任意の組織のディレクトリ内のアカウント] に変更します。

Microsoft Entra 管理センターでシングル テナント アプリケーションが作成されると、[概要] ページに一覧表示される項目の 1 つがアプリケーション ID URI になります。 これは、プロトコル メッセージでアプリケーションが識別される方法の 1 つであり、いつでも追加できます。 シングル テナント アプリのアプリ ID URI は、そのテナント内でグローバルに一意であれば問題ありません。 これに対し、マルチテナント アプリの場合は、すべてのテナントでグローバルに一意である必要があります。これにより、Microsoft Entra ID がすべてのテナントでアプリを見つけられるようになります。

たとえば、テナントの名前が contoso.onmicrosoft.com である場合、有効なアプリケーション ID URI は、https://contoso.onmicrosoft.com/myapp のようになります。 アプリ ID URI がこのパターンに従っていないと、アプリケーションのマルチテナントとしての設定が失敗します。

コードを更新して、要求を /common エンドポイントに送信するようにする

マルチテナント アプリケーションでは、アプリケーションがユーザーのサインイン元のテナントをすぐには認識できないため、要求をテナントのエンドポイントに送信することはできません。 代わりに、要求は Microsoft Entra のすべてのテナントにまたがる共通のエンドポイント (https://login.microsoftonline.com/common) に送信され、要求を処理するセントラル ハブとして機能します。

IDE でアプリを開き、コードを編集して、テナント ID の値を /common に変更してください。 このエンドポイントはテナントや発行者自体ではありません。 Microsoft ID プラットフォームは、/common エンドポイントで要求を受信すると、ユーザーのサインインを行い、それによってユーザーのサインイン元のテナントを特定します。 このエンドポイントは、Microsoft Entra ID でサポートされるすべての認証プロトコル (OpenID Connect、OAuth 2.0、SAML 2.0、WS-Federation) に対応しています。

その後のアプリケーションに対するサインイン応答には、ユーザーを表すトークンが含まれます。 アプリケーションは、トークンの issuer 値に基づいてユーザーのサインイン元のテナントを特定できます。 /common エンドポイントから応答が返された場合、トークン内の issuer 値はユーザーのテナントに対応しています。

Note

実際には、マルチテナント アプリケーションには次の 2 つの機関があります。

  • 任意の組織のディレクトリ (Microsoft Entra ディレクトリ) 内のアカウントと、個人用の Microsoft アカウント (Skype、Xbox など) を処理するアプリケーション向けの https://login.microsoftonline.com/common
  • 任意の組織ディレクトリ内のアカウント (任意の Microsoft Entra ディレクトリ) を処理するアプリケーション向けの https://login.microsoftonline.com/organizations

このドキュメントの説明では、common を使用します。 ただし、アプリケーションで Microsoft 個人アカウントがサポートされていない場合は、organizations で置き換えることができます。

複数の issuer 値を処理するようにコードを更新する

Web アプリケーションと Web API は、Microsoft ID プラットフォームからトークンを受信して検証します。 ネイティブ クライアント アプリケーションでは、アクセス トークンを検証せず、トークンを不透明なものとして処理する必要があります。 これらのアプリケーションは、Microsoft ID プラットフォームにトークンを要求して受信し、それらを API に送信します。その後、API でトークンが検証されます。

マルチテナント アプリケーションは、トークンの検証時に追加のチェックを実行する必要があります。 マルチテナント アプリケーションは、/organizations または /common キー URL からのキー メタデータを使用するように構成されています。 アプリケーションでは、公開されたメタデータ内の issuer プロパティが、トークン内の iss 要求にテナント ID (tid) 要求が含まれていることを示す通常のチェックに加えて、トークン内の iss 要求と一致することを検証する必要があります。 詳細については、「トークンの検証」を参照してください。

Microsoft Entra ID のアプリケーションにユーザーがサインインするには、そのアプリケーションがユーザーのテナントに表示される必要があります。 このようにすることで、組織では、ユーザーがテナントからアプリケーションにサインインする場合に一意のポリシーを適用するなどの操作を行うことができます。 シングルテナント アプリケーションの場合は、Microsoft Entra 管理センターを通じて登録を使用できます。

マルチテナント アプリケーションの場合、アプリケーションの最初の登録は、開発者が使用する Microsoft Entra テナントに保存されます。 ユーザーが初めて別のテナントからこのアプリケーションにサインインすると、Microsoft Entra ID により、アプリケーションで要求されるアクセス許可に同意するかどうかを尋ねられます。 同意した場合、アプリケーションを表す "サービス プリンシパル" と呼ばれるものがユーザーのテナントに作成され、サインインを続行できます。 また、アプリケーションに対するユーザーの同意を記録するデリゲートが、ディレクトリに作成されます。 アプリケーションのアプリケーション オブジェクトおよびサービス プリンシパル オブジェクトの詳細と、それらの関係については、アプリケーション オブジェクトとサービス プリンシパル オブジェクトに関するページを参照してください。

単一層アプリに対するユーザーの同意を示す図。

この同意は、アプリケーションから要求されるアクセス許可によって異なります。 Microsoft ID プラットフォームでは、次の 2 種類のアクセス許可がサポートされています。

  • 委任: このアクセス許可を付与されると、アプリケーションは、サインイン済みのユーザーとして、そのユーザーが実行可能な操作の一部を行うことができます。 たとえば、アプリケーションに対し、サインイン済みユーザーのカレンダーを読み取る委任アクセス許可を付与できます。
  • アプリケーション専用: このアクセス許可は、アプリケーションの ID に直接付与されます。 たとえば、アプリケーションに、アプリケーションにサインインしているユーザーに関係なく、テナントのユーザーの一覧を読み取るアプリケーション専用アクセス許可を付与できます。

アクセス許可には、通常のユーザーが同意できるものと、テナント管理者の同意が必要なものがあります。

ユーザーおよび管理者の同意の詳細については、「管理者の同意ワークフローの構成」を参照してください。

アプリケーション専用アクセス許可では、常にテナント管理者の同意が必要になります。 アプリケーションがアプリケーション専用アクセス許可を要求する場合に、ユーザーがそのアプリケーションにサインインしようとすると、このユーザーは同意できないことを示すエラー メッセージが表示されます。

一部の委任アクセス許可でも、テナント管理者の同意が必要になります。 たとえば、サインイン済みユーザーとして Microsoft Entra ID に書き戻しを行うアクセス許可には、テナント管理者の同意が必要です。 アプリケーション専用アクセス許可と同様に、管理者の同意が必要な委任アクセス許可を要求するアプリケーションに通常のユーザーがサインインしようとすると、アプリでエラーが発生します。 アクセス許可に管理者の同意が必要かどうかは、リソースを公開した開発者により決定されており、リソースのドキュメントに記載されています。 Microsoft Graph API のアクセス許可に関するドキュメントには、管理者の同意が必要なアクセス許可が示されています。

アプリケーションで管理者の同意が必要なアクセス許可を使用する場合は、管理者が操作を開始できるボタンやリンクを追加することを検討してください。 通常、この操作に対してアプリケーションから送信される要求は OAuth2/OpenID Connect 承認要求ですが、この要求には prompt=consent クエリ文字列パラメーターも含まれています。 管理者が同意し、ユーザーのテナントにサービス プリンシパルが作成されると、以降のサインイン要求では prompt=consent パラメーターは不要になります。 管理者は要求されたアクセス許可を許容可能と判断しているため、その時点からは、テナント内の他のユーザーが同意を求められることはありません。

テナント管理者は、通常ユーザーによるアプリケーションへの同意を無効にすることができます。 通常ユーザーによる同意が無効化された場合、テナントでアプリケーションを使用するには常に管理者の同意が必要になります。 Microsoft Entra 管理センターでは、エンドユーザーの同意を無効にしてアプリケーションをテストできます。 [エンタープライズ アプリケーション]>[同意とアクセス許可] で、[ユーザーの同意を許可しない] を選択します。

prompt=consent パラメーターは、管理者の同意を必要としないアクセス許可を要求するアプリケーションでも使用できます。 この方法が使用される例として、アプリケーションで、テナント管理者が一度 "サインアップ" すると、その時点から他のユーザーが同意を求められないエクスペリエンスを必要とする場合があります。

アプリケーションが管理者の同意を必要とし、管理者はサインインしたが、prompt=consent パラメーターが送信されない場合、管理者がアプリケーションへの同意に成功すると、自分のユーザー アカウントについてのみ適用されます。 通常のユーザーは、アプリケーションへのサインインも同意も実行できないままです。 この機能は、他のユーザーのアクセスを許可する前に、テナント管理者がアプリケーションを調査できるようにしたい場合に役立ちます。

一部のアプリケーションは多層化されており、それぞれの層が個別の Microsoft Entra ID 登録で表されている場合があります。 たとえば、Web API を呼び出すネイティブ アプリケーションや、Web API を呼び出す Web アプリケーションなどです。 どちらの場合でも、クライアント (ネイティブ アプリケーションまたは Web アプリケーション) は、リソース (Web API) を呼び出すアクセス許可を要求します。 クライアントがユーザーのテナントに対する同意を得られるようにするには、アクセス許可を要求されるリソースがすべて、あらかじめユーザーのテナントに存在する必要があります。 この条件が満たされない場合、Microsoft Entra ID は、最初にリソースを追加する必要があることを示すエラーを返します。

1 つのテナント内の複数の階層

この処理は、論理アプリケーションが 2 つ以上のアプリケーション登録 (別々のクライアントとリソースなど) で構成されている場合に問題になる可能性があります。 まず、外部テナントにリソースを追加するにはどうすればいいのでしょうか。 Microsoft Entra ID では、ワンステップでクライアントとリソースが同意されるようにすることによって、この状況に対応します。 ユーザーには、同意ページにクライアントとリソースの両方によって要求されたアクセス許可の合計が表示されます。 この動作を有効にするには、リソースのアプリケーション登録で、アプリケーションのマニフェストknownClientApplications というクライアントのアプリ ID を含める必要があります。 次に例を示します。

"knownClientApplications": ["12ab34cd-56ef-78gh-90ij11kl12mn"]

これは、マルチテナント アプリケーションのサンプルで実証されています。 次の図は、1 つのテナントに登録されている多層アプリケーションのための同意の概要を示しています。

多層の既知のクライアント アプリへの同意を示す図。

複数のテナント内の複数の階層

同様のケースは、アプリケーションの各層を別々のテナントに登録する場合にも起こります。 たとえば、Exchange Online API を呼び出すネイティブ クライアント アプリケーションを構築する場合を考えます。 ネイティブ アプリケーションを開発するため、また開発後にユーザーのテナントでこのネイティブ アプリケーションを実行するために、Exchange Online のサービス プリンシパルが存在する必要があります。 この場合、開発者とユーザーは、テナントでサービス プリンシパルを作成するために、Exchange Online を購入する必要があります。

API が Microsoft 以外の組織によって作成されている場合、この API の開発者は、ユーザーがユーザーのテナントでアプリケーションに対して同意する手段を提供する必要があります。 推奨される設計は、サード パーティー開発者向けに、サインアップを実装する Web クライアントとしても機能できるような API を構築することです。 手順は次のとおりです。

  1. 前述のセクションに従って、API がマルチテナント アプリケーションの登録およびコード要件を実装していることを確認します。
  2. API のスコープとロールの公開に加えて、登録に、"サインインとユーザー プロファイルの読み取り" アクセス許可 (既定で提供) が含まれていることを確認します。
  3. Web クライアントでサインイン/サインアップ ページを実装し、管理者の同意のガイダンスに従います。
  4. ユーザーがアプリケーションに同意し、テナントにサービス プリンシパルと同意の委任のリンクが作成されたら、ネイティブ アプリケーションで API のトークンを取得できます。

次の図に、異なるテナントに登録されている多層アプリケーションの同意の概要を示します。

多層の複数のアプリへの同意を示す図。

ユーザーおよび管理者は、次の方法により、いつでもアプリケーションに対する同意を取り消すことができます。

  • ユーザーは、[アクセス パネル アプリケーション] リストから個々のアプリケーションを削除することで、アプリケーションへのアクセス許可を取り消します。
  • 管理者は、Microsoft Entra 管理センターの [エンタープライズ アプリケーション] セクションを使用してアプリケーションを削除することで、アプリケーションへのアクセス許可を取り消します。 アプリケーションを選択し、[アクセス許可] タブに移動してアクセスを取り消します。

管理者が、テナント内のすべてのユーザーについてアプリケーションへの同意を行った場合、ユーザーが個別にアクセス許可を取り消すことはできません。 アクセス許可を取り消すことができるのは管理者のみであり、取り消しの対象はすべてのアプリケーションのみになります。

マルチテナント アプリケーションとアクセス トークンのキャッシュ

マルチテナント アプリケーションでは、Microsoft Entra ID で保護されている API を呼び出すアクセス トークンを取得することもできます。 マルチテナント アプリケーションで Active Directory 認証ライブラリ (MSAL) を使用する際によくあるエラーは、最初に /common を使用してユーザーのトークンを要求し、応答を受信した後で、同じユーザーの後続のトークンも /common を使用して要求することです。 Microsoft Entra ID からの応答は /common ではなくテナントから送信されるため、MSAL ではトークンがテナントから送信されたものとしてキャッシュされます。 ユーザーのアクセス トークンを取得するためのその後の /common への呼び出しでは、キャッシュ エントリが見つからないため、ユーザーはもう一度サインインするように求められます。 キャッシュが見つからない問題を回避するために、サインイン済みのユーザーに対する以降の呼び出しは、テナントのエンドポイントに向けて行われるようにしてください。

関連項目