アプリケーションをマルチテナントにする

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

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

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

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

なお、サンプル「Azure AD と OpenID Connect を使用して Microsoft Graph を呼び出すマルチテナント SaaS Web アプリケーションを構築する」も参考にできます。 このハウツーでは、読者が Azure AD のシングルテナント アプリケーションの構築に慣れていることを前提としています。 慣れていない場合は、開発者ガイドのホームページにある、いずれかのクイックスタートから始めてください。

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

既定では、Azure AD での Web アプリケーション/API 登録は、作成時点でシングルテナントです。 登録をマルチテナントにするには、Azure portal にあるアプリケーション登録の [認証] ペインで、[サポートされているアカウントの種類] セクションを探します。 設定を [任意の組織のディレクトリ内のアカウント] に変更します。

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

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

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

マルチテナント アプリケーションでは、アプリケーションがユーザーのサインイン元のテナントをすぐには認識できないため、要求をテナントのエンドポイントに送信することはできません。 このため、要求は、すべての Azure AD テナントと多重通信するエンドポイントに送信されます。https://login.microsoftonline.com/common

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

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

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

Web アプリケーションと Web API は、Microsoft ID プラットフォームからトークンを受信して検証します。 ネイティブ クライアント アプリケーションでは、アクセス トークンを検証せず、トークンを不透明なものとして処理する必要があります。 これらのアプリケーションは、Microsoft ID プラットフォームにトークンを要求して受信し、それらを API に送信します。その後、API でトークンが検証されます。 マルチテナント アプリケーションでは、メタデータの issuer 値をトークンの issuer 値と照合することでは、トークンを検証できません。 マルチテナント アプリケーションでは、issuer 値のテナント ID 部分に基づいて、issuer 値が有効であるかどうかを判定するためのロジックが必要になります。

たとえば、マルチテナント アプリケーションで、アプリケーションのサービスにサインアップしている特定のテナントからのサインインのみを許可するには、トークンの issuer 値または tid 要求値のいずれかを調べて、サブスクライバーのリストにテナントが含まれていることを確認する必要があります。 マルチテナント アプリケーションではユーザーのみを処理して、テナントに基づくアクセスの判定を行わない場合は、issuer 値を完全に無視することができます。

マルチテナントのサンプルでは、Azure AD テナントでサインインできるようにするために、issuer の検証が無効化されています。 /common エンドポイントはテナントに対応しておらず発行者でもないので、/common のメタデータの issuer 値を確認すると、実際の値の代わりに次のようなテンプレート URL が表示されます。

https://sts.windows.net/{tenantid}/

アプリで複数のテナントをサポートできるようにするには、コードの関連セクションを変更して、issuer 値が {tenantid} に設定されている状態にします。

これに対し、シングルテナント アプリケーションは通常、エンドポイント値を受け取って、次のようなメタデータ URL を構築します。

https://login.microsoftonline.com/contoso.onmicrosoft.com/.well-known/openid-configuration

さらに、この URL を使用して、トークンの検証に使用する 2 種類の重要な情報である、テナントの署名キーと issuer 値をダウンロードします。

各 Azure AD テナントは、次のような形をした一意の issuer 値を持ちます。

https://sts.windows.net/31537af4-6d77-4bb9-a681-d2394888ea26/

ここで、GUID の値は、テナントのテナント ID を名前変更できるようにしたものです。

シングルテナント アプリケーションでトークンを検証する際、トークンの署名を、メタデータ ドキュメントからの署名キーに照らしてチェックします。 このテストにより、トークン内の issuer 値が、メタデータ ドキュメント内で見つかった値に一致することを確認できます。

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

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

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

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

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

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

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

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

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

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

テナント管理者は、通常ユーザーによるアプリケーションへの同意を無効にすることができます。 通常ユーザーによる同意が無効化された場合、テナントでアプリケーションを使用するには常に管理者の同意が必要になります。 エンド ユーザーによる同意を無効化した状態でアプリケーションをテストする場合は、Azure portal[エンタープライズ アプリケーション][ユーザー設定] セクションで構成スイッチを見つけることができます。

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

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

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

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

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

"knownClientApplications": ["94da0930-763f-45c7-8d26-04d5938baab2"]

この方法については、この記事の末尾の「関連コンテンツ」セクションにある多層ネイティブ クライアントによる Web API 呼び出しのサンプルを参照してください。 次の図は、1 つのテナントに登録されている多層アプリケーションのための同意の概要を示しています。

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

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

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

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

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

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

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

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

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

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

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

次のステップ

この記事では、シングル テナント アプリケーションをマルチテナント アプリケーションに変換する方法について説明しました。 アプリと Azure AD の間でのシングル サインオン (SSO) を有効にした後には、アプリケーションを更新して、Microsoft 365 のように、Microsoft リソースによって公開される API にアクセスするようにします。 これにより、パーソナライズされたエクスペリエンスをアプリケーションで提供できます。たとえば、プロファイル画像や予定表の予定などのコンテキスト情報をユーザーに表示できます。

Azure AD や、Exchange、SharePoint、OneDrive、OneNote などの Microsoft 365 サービスへの API 呼び出しを行う方法の詳細については、Microsoft Graph API に関するページを参照してください。