エクスポート (0) 印刷
すべて展開

Azure AD でのマルチテナント Web アプリケーションの開発

更新日: 2014年5月

noteメモ
このサンプルは有効期限が切れています。テクノロジ、メソッド、またはインターフェイスの命令、あるいはこれらがすべて新しい機能に置き換えられています。類似したアプリケーションを構築する更新済みのサンプルについては、「WebApp-MultiTenant-OpenIdConnect-DotNet」を参照してください。

開発者向け Azure AD シリーズの最初のホワイト ペーパーでは、Azure AD テナントを利用してユーザーが基幹業務 (LoB) アプリケーション、オンプレミス、およびクラウドで Web サインオンを使用できるようにする方法を学習しました。次を参照してください: Azure AD を使用してサインオンを Web アプリケーションに追加

それを基にして書かれた 2 番目のホワイト ペーパーでは、LoB アプリケーションが Graph API を使用して情報のクエリを直接実行できるようにする方法を示しました。次を参照してください: Graph API を使用した Azure AD のクエリ

このホワイト ペーパーでは、Azure AD に関する次のレベルの知識として、最初の 2 つの記事で学習した Azure AD の機能を利用し、複数のテナントで動作して新しい顧客の使用開始を自動化するように設計された SaaS (サービスとしてのソフトウェア) アプリケーションの開発方法を説明します。

SaaS アプリケーション開発での一般的な課題は、ほとんどが、顧客の使用開始と、顧客の ID インフラストラクチャへのアクセスに関するものです。すべての潜在的顧客は異なる Web サインオン ソリューションを使用しており、顧客が使いやすくてアプリケーションが管理しやすい使用開始プロセスの標準化は非常に困難です。また、すべての潜在的顧客は、ID とディレクトリ データをクラウド アプリケーションからアクセスできないインフラストラクチャに保持しています。

Azure AD は、両方の課題に対してシンプルなソリューションを提供します。最初のホワイト ペーパーでは、ディレクトリ テナントにアクセスするために開発されたアプリケーションを、管理者が Azure 管理ポータルを使用して登録する方法を学習しました。このチュートリアルでは、同じアプリケーションを他の Azure AD テナントからアクセスできるように構成する方法を学習します。Azure AD のメカニズムを使用すると、アプリケーション自体で潜在的顧客の管理者に対してディレクトリ テナントへのアクセスを許可するように要求できます。これは、Azure AD 管理ポータルを使用して顧客の管理者に同意 UI を提示することによって実現されます。この操作は、人気のあるほとんどのソーシャル Web アプリケーションで一般的になっている同意ジェスチャとあまり変わりありません。

このドキュメントでは、最初の 2 つのホワイト ペーパーで開発した MVC 4 アプリケーションの Azure AD のエントリを変更することによって、アプリケーションを複数の Azure AD テナントで使用できるようにする方法を説明します。さらに、単一テナント接続用のソリューションから、複数の顧客の組織を追加できる完全なマルチテナント ソリューションへの以降のために、アプリケーションに適用する必要のあるコード変更を示します。チュートリアルの説明の途中には、ここで説明するサンプル アプリケーションの狭い範囲を超えて、Azure AD の機能を理解するために必要な上位レベルの概念についての説明も示されています。

繰り返しますが、ここで説明するタスクはすべて、最初の 2 つのペーパーで開発したソリューションへの追加作業なので、このペーパーは必ず、最初の 2 つのペーパーを読んで指示に従った後で読んでください。

このドキュメントは以下のセクションで構成されています。

  • 前提条件: チュートリアルを完了するために満たす必要があるすべての要件を示します。

  • ソリューション アーキテクチャ: Azure AD を利用する SaaS アプリケーションの構成方法の 1 つについて概要を説明します。

  • Windows AD でのアプリケーション エントリの外部使用可能への昇格: Azure ポータルの LoB アプリケーションのエントリを再確認し、既存のアプリケーションを自身のディレクトリ テナント以外で使用できるように拡張するための変更について説明します。

  • 複数のテナントを処理するための VS でのアプリケーション プロジェクトの準備: 現在は単一のディレクトリ テナントで Web サインオンと Graph アクセスを実行している MVC 4 アプリケーションのソース コードを、Azure AD テナントの動的なセットを処理するように変更する方法を示します。複数のサブセクションを通じて、マルチテナントの事例に一般化する必要のあるアプリ ID 管理のさまざまな側面を順を追って学習します。

  • アプリケーションにサインアップ機能を追加する: 現在は単一のディレクトリ テナントで Web サインオンと Graph アクセスを実行している MVC 4 アプリケーションのソース コードを、Azure AD テナントの動的なセットを処理するように変更する方法を示します。複数のサブセクションを通じて、マルチテナントの事例に一般化する必要のあるアプリ ID 管理のさまざまな側面を順を追って学習します。

  • 省略可能:テスト サブスクリプションを作成する: 最初のチュートリアルで作成した Azure サブスクリプションには自身が所有する 1 つのディレクトリのみが含まれていますが、マルチテナント ワークロードでのアプリケーションの動作をテストするには、自身の Azure AD テナント以外のテナントにもアクセスする必要があります。このセクションではその方法を説明します。

  • アプリケーションをテストする: チュートリアルのすべてのタスクが連携して SaaS アプリケーションの一貫したエンド ツー エンド エクスペリエンスを作成する方法を説明します。

このチュートリアルを完了するには、次の前提条件を満たす必要があります。

マルチテナント アプリケーションのソリューション アーキテクチャ

従来の基幹業務アプリケーションは、アプリケーションを開発して配置した最初の場所の同じ組織のユーザーがアクセスおよび管理するようになっています。 一方、SaaS (Software as a Service: サービスとしてのソフトウェア) として提供されるビジネス アプリケーションは、独立したソフトウェア ベンダーによって開発および運用され、サードパーティの組織によって使用されるようになっています。このようなアプリケーションは、マルチテナント リソースとして作成されるのが一般的です。マルチテナント リソースとは、複数の顧客組織 (テナント) によって共有されるアプリケーションであり、すべてのテナントはアプリケーションが顧客に専用のものであるように使用できます。

概要で説明したように、Azure AD では、既存の LoB アプリケーションを、他の Azure AD テナント管理者 (見込み客) がそれぞれの組織で使用できるようにすることができます。すべての見込み客の管理者は、特別な URL に移動して、自分の Azure AD テナントにサインインする必要があります。管理者がアクセスするページには、アプリケーション、発行者、ディレクトリで必要なアクセス レベル (SSO、SSO と読み取り専用アクセス、SSO と読み書き) についての説明があります。顧客の管理者は、ページのコントロールを使用して、アプリケーションが自分の Azure ディレクトリにアクセスすることに同意することを許可でき、その場合、管理ポータルは自動的にアプリケーションを顧客の Azure AD テナントに登録するので、それ以上の作業は必要ありません。

LoB チュートリアルで作成された MVC 4 アプリケーションには、統合するように構成されている Azure AD テナントへの直接参照が含まれます。つまり、アプリケーションはすべての非認証要求をテナント固有のサインオン アドレスにリダイレクトし、その固有のテナントからのトークンのみを受け入れるように構成されています。このチュートリアルでは、任意の登録済み顧客テナントでの Web サインオンと Graph API 呼び出しをアプリケーションが処理できるように、アプリケーションの ID 管理ロジックを一般化します。もう 1 つの重要な機能領域は、見込み客を前述の同意ページにリダイレクトし、結果を処理して、有効な機関として受け入れられた Azure AD テナントのリストを動的に拡張する機能を追加することです。そのすべては、少数の戦略的領域での WIF の拡張性モデルを利用することによって実現します。

変更後のアプリケーションのアーキテクチャの中心的なコンポーネントは、MultiTenantIssuerNameRegistry (以降では MTINR と呼びます) およびそのテナントの永続ストアです。

MTINR は、有効な認証ソースと見なされているすべての Azure AD テナントのリストを保持しています。このリストは次のとおりです。

  • サインオン時に参照されます。登録されているテナントによって発行されたトークンだけが有効であると見なされます。

  • サインアップ時に更新されます。アプリケーションがディレクトリにアクセスすることに見込み客が許可すると、管理ポータルはユーザーを関連するテナント ID と共にアプリケーションにリダイレクトします。このチュートリアルでは、そのメッセージをプログラムで処理して新しい顧客を MTINR リストに追加する方法を示します。

また、MTINR は、Azure AD から送信されたトークンの署名を確認するために使用されるキーも保持しています。このドキュメントでは、自動キー更新ロジックを変更して、アプリケーションがサービスでのキー ロール イベントを追跡してダウンタイムを最小にする方法を示します。

サインアップ手順を追加するということは、アプリケーションが非認証済みユーザーにも UI を提供できる必要があることを意味します。LoB アプリケーション チュートリアルで示した包括的保護ポリシーではなく、選択的に Web サインオン要件をコントローラーに適用するように WIF の設定を変更する方法を説明します。

最初に、アプリケーションを他の Azure AD テナントで使用できるようにすることを Azure AD に認識させます。そのためには、Azure 管理ポータルでアプリケーションの設定を変更します。

Azure 管理ポータルに移動し、LoB および Graph API のチュートリアルで使用したものと同じアカウントでサインインします。[Active Directory] タブに移動し、ディレクトリを選択し、[アプリケーション] ヘッダーをクリックし、LoB チュートリアルで作成したアプリケーションのエントリを探して、クリックします。

登録プロセスの再度に表示したものと同じ [クイック スタート] ページに移動します。[構成] ヘッダーをクリックします。

noteメモ
最後のチュートリアルで [次回アクセス時はクイック スタートをスキップする] ボックスをオンにした場合は、[構成] 画面に直接移動します。

外部アクセス

ページの中ほどに、[外部アクセス] スイッチがあります。

このスイッチの既定値はオフです。作成時、アプリケーションは作成されたときの Azure AD テナントの同じユーザーによってのみアクセス可能なように構成されます。

外部アクセスをオンにすると、他のテナントがそれぞれのディレクトリ内でアプリケーションをプロビジョニングできるようになります。具体的には、Azure AD は、他のテナントの管理者がそれぞれのディレクトリにアクセスするためのアプリケーション権限を付与するために使用できる顧客同意 URL をアクティブ化します。顧客がアプリケーションに同意すると、アプリケーションを記述しているエントリのプロビジョニングが顧客の Azure AD テナント内でトリガーされ、アプリケーション パラメーター (APP ID URIAPP URL、Graph API へのアクセスに使用されるキーなど) がページに設定されます。

Important重要
アプリケーションの外部アクセスを有効にしても、アプリケーションが自分の Azure AD テナントに対して既に保有している既存の権限は変更されません。さらに、アプリケーションの外部アクセスを無効にしても、有効であった期間に自分または他のテナントに対して付与されたアクセス レベルは影響を受けません。つまり、このスイッチは外部顧客に対する同意エクスペリエンスおよび関連するプロビジョニング メカニズムの可用性にのみ影響します。作成を助けたアプリケーション エントリには影響しません。

スイッチの [オン] をクリックします。ボタンが紫に変わり、画面の下部のコマンド バーに [保存] ボタンが表示されます。[保存] ボタンをクリックしても何も起こりませんが、表示されるエラー メッセージを理解しておくことが重要です。

構成の更新に失敗しました

更新操作が失敗しました。問題をトラブルシューティングするには [詳細] アイコンをクリックしてください。

失敗の詳細

このメッセージは、APP ID URI の形式がこの操作に対して有効ではないことを示しています。

外部から使用可能なアプリケーションに多くのユーザーがアクセスでき、それらのユーザーがアプリケーションを提供する組織と業務上のつながりがない可能性がある場合、Azure AD はその種のアプリケーションに対してユーザーの識別を容易にする追加の要件を適用します。

LoB アプリケーションは URI を APP ID URI 値として持つことができますが (唯一の制約はテナント レベルでの一意性)、アプリケーションは外部使用可能として設定されるには次の要件に従う必要があります。

  • プロトコル スキームとして https:// を使用する URI だけが受け付けられます

  • URI のホスト部分は、Azure AD テナントに関連付けられている検証済みドメインに対応する必要があります

Azure AD で使用したいカスタム ドメインがある場合は、ここの指示に従って検証できます。検証済みのカスタム ドメインは [ドメイン] ヘッダーの下にあります。これは、テナントの Azure 管理ポータル ページの [アプリケーション] ヘッダーのピアです。

カスタム ドメインがない場合、またはカスタム ドメインを使用しない場合は、すべての Azure AD テナントに割り当てられる <tenantname>.onmicrosoft.com. 形式の既定の 3 レベル ドメインを利用できます。この既定のオプションが安全であると仮定して、ここではその方法に従います。

ページ下部のシングル サインオン セクションまでスクロール ダウンします。App ID URI を編集して、値 https://<tenantname>.onmicrosoft.com/ExpenseReport を入力します。文字列 <tenantname> は、実際の Azure AD テナントの名前に置き換えます。[保存] を再びクリックします。

APP ID URI の形式が正しいと、今度は更新操作が成功します。管理ポータルでは画面の下部にメッセージ トースターが表示されますが、次の図で示すように、アプリケーション設定の重要な変更によってもわかります。

アクセス許可の URL

外部アクセス スイッチは完全に [オン] の位置にあります。また、[アクセス許可の URL] というラベルが付いた新しいテキスト ボックスもあります。これは、見込み客がアプリケーションへのディレクトリ アクセスを許可するために使用するエンドポイントの URL です。URL の構造については、後でサインアップ機能をアプリケーション コードに統合するときに詳しく説明します。

自身の Azure AD テナントに関しては、この時点で、アプリケーションはマルチテナントとして機能できます。次に、アプリケーションのコードを変更する必要があります。

noteメモ
このチュートリアルは、まだアプリケーションのライフサイクルの開発ステージです。アプリケーションを稼働できるようになったら、この画面に戻って、アプリケーションの同意ページの表示を調整し (適切なロゴをアップロードすることによって)、アプリケーションの応答 URL を本番アドレスに変更します。後者については、LoB アプリケーション チュートリアルの「Azure Web サイトへのアプリケーションの展開」セクションの手順を使用できます。実際の展開手順はターゲット環境によって異なりますが、管理ポータルでのアプリケーション エントリの更新に関する手順は同じように適用できます。

前のチュートリアルで作成した MVC 4 プロジェクトを Visual Studio 2012 で開きます。

「ソリューション アーキテクチャ」で説明したように、最初の 2 つのチュートリアルで作成した LoB アプリケーションにマルチテナント性を追加するには複数の変更を適用する必要があります。 機能領域ごとにこれらの変更をインクリメンタルに適用します。シリーズの他のチュートリアルと併せて、メインの目標は、学習したことを実際のアプリケーションに適用できるように何が起こるかを理解することです。

noteメモ
ここで提案される変更は、これまで作成したコードのリファクタリングの最小化も試みます。これによりチュートリアルに従いやすくしている一部の冗長性 (たとえば、より一般的な方法での複数の機能の統合ではなく、新しいコントローラーの作成) がもたらされますが、必要に応じて自由にリファクタリングおよび機能の正規化を行う必要があります。

最初に、Web.config で WS-Federation 座標を更新して新しい設定を反映します。プロジェクト エクスプローラーで Web.config を探して開きます。

noteメモ
LoB チュートリアルの「WIF 設定の詳細」をまだ読んでいない場合は、読んでください。一部のタスクは ID およびアクセス ツールで実行できますが、ここでは Web.config を直接編集します。その方が必要な変更についていっそうよくわかります。

<system.identityModel> セクションまで下にスクロールします。identityConfiguration/AudienceURI 要素にまだ古い APP ID URI 値が含まれていることがわかります。次のように、Azure 管理ポータルで入力した新しい値に変更します。

<system.identityModel>
    <identityConfiguration>
      <audienceUris>
        <add value=”https://<tenantname>.onmicrosoft.com/ExpenseReport” />
      </audienceUris> 

これにより、アプリケーションは新しい APP ID URI を対象とする有効なトークンとして受け付けます。

system.identityModel.Services/federationConfiguration<wsFederation> 要素までさらにスクロールします。

ここでは 2 つの変更を加える必要があります。

  • realm 属性の値を、前の <audienceUris> セクションに対して使用したものと同じ APP ID URI に変更します。

  • issuer 属性の値を、テナント ID の GUID と文字列 common に置き換えます。

<federationConfiguration>
   <cookieHandler requireSsl="false" />
   <wsFederation passiveRedirectEnabled="true" issuer="https://login.windows.net/common/wsfed" realm="https://<tenantname>.onmicrosoft.com/ExpenseReport" requireHttps="false" />
</federationConfiguration> 

realm の値は、WS-Federation パラメーター wtrealm の値に対応しており、要求されたトークンで意図される受信者を示すために機関 (ID プロバイダー) へのサインイン メッセージに含まれます。この値は、ターゲットの Azure AD テナントでアプリケーションを識別する値と一致する必要があります。

issuer の値は、サインオン要求を受け取る必要があるエンドポイントを示します。最初のチュートリアルでは、これは自身の Azure テナントに対応しますが、ここでは、アプリケーションによるアクセスに同意したすべてのテナントのうち、次のユーザーがどのテナントに属するかは前もってわかりません。Azure AD では、一般にテナント独立エンドポイントと呼ばれる特殊なエンドポイントが提供されます。これを使用すると、アプリケーションは、使用するテナントの決定をユーザーがユーザー名を入力する時点まで延期できます。ユーザー名にドメイン情報が含まれていれば、その時点でテナントの選択が一意に決定され、認証が通常どおり行われます。

noteメモ
Azure AD がユーザーにトークンを発行するのは、受信アプリケーション (前に説明したように realm パラメーターで示されている) がユーザーの Azure AD テナント内でアクセスを許可されている場合のみであることに注意してください。テナント独立エンドポイントを使用しても、ディレクトリ レベルで確立されたアクセス制約は弱くなりません。サインオン プロセスに一般性が追加されるだけです。

再び、Web.config ファイルでIssuerNameRegistry 要素にスクロールします。

最初のチュートリアルで説明したように、この要素は、有効なトークン、トークンの署名を検証するために使用する必要がある X.509 証明書のサムプリント、信頼できる Azure AD テナントを示す発行者の値を定義するパラメーターを記録するためのものです。

この情報はマルチテナントの場合も関係があります。主な違いは、単一の値ではなく、アプリケーションの顧客テナントに対応する許容される発行者のリストがあることです。 IssuerNameRegistry を実装するために使用されるクラス ValidatingIssuerNameRegistry (VINR) は、<validIssuers> 要素の複数エントリに対応します。ただし、マルチテナント アプリケーションは、既存の顧客に対応している間に新しい顧客を獲得する可能性がありWeb.config の編集はアプリケーションの可用性に意図しない影響があります。

この問題を避けるため、このチュートリアルでは、テナントの情報を外部ファイルに保存し、その外部ファイルを検証調整のソースとして使用するカスタム VINR 実装を作成します。

noteメモ
このチュートリアルでは、ストアの機能ロールを示すための最低限のものを実装します。実際のアプリケーションのパフォーマンスでは、ストアの可用性と堅牢性がソリューションの重要な側面になります。

外部ストアの作成を始めます。Content フォルダーに新しい XML ファイルを作成し (ソリューション エクスプローラーContent を右クリックし、[新しい項目の追加] をクリックし、左側で [データ] カテゴリを選択し、XML ファイルを選択)、tenants.xml という名前を付けます。

ファイルに以下を貼り付けます。

<?xml version="1.0" encoding="utf-8" ?>
<authority>
  <tenants>
    <tenant id="95ca3807-2313-4cfe-93b3-20ef9f46ae88" />    
  </tenants>
  <keys>
    <key id="3A38FA984E8560F19AADC9F86FE9594BB6AD049B" />
  </keys>
</authority>

<tenants> および <keys> 要素は空白のままにしておいても、現在の IssuerNameRegistrythumbprint および tenantID の値を設定してもかまいません。いずれにしても、アプリケーションには既に Azure AD テナントに対するアクセス権限があります。

外部リポジトリができたので、ソース検証を使用してカスタム VINR 実装を作成します。

プロジェクトのルートに新しい AADUtils フォルダーを作成します。フォルダーを右クリックし、[追加] を選択し、[新しい項目] をクリックし、左のカテゴリでコードを選択し、[クラス] をクリックし、ファイルに MultiTenantIssuerNameRegistry という名前を設定します。

ディレクティブを使用して以下を追加します。

using System.IdentityModel.Tokens;
using System.Xml.Linq;

新しいクラスを VINR の実装にします。tenants.xml のパスと内容を追跡するための 2 つの静的プロパティを追加し、作成時に初期化するための静的既定コンストラクターを追加します (メソッドはすべて静的です)。

namespace ExpenseReport.AADUtils
{
    public class MultiTenantIssuerNameRegistry: ValidatingIssuerNameRegistry
    {
        private static XDocument doc;
        private static string filePath;

        static MultiTenantIssuerNameRegistry()
        {
            filePath = HttpContext.Current.Server.MapPath("~/Content/tenants.xml");
            doc = XDocument.Load(filePath);
        }
    }
}

リポジトリに tenantID またはキーがあるかどうかを調べるメソッドを追加します。

public static bool ContainsTenant(string tenantId)
{
    return 
    doc.Descendants("tenant").Where(x => x.Attribute("id").Value == tenantId).Any();
}

public static bool ContainsKey(string thumbprint)
{
    return 
    doc.Descendants("key").Where(x => x.Attribute("id").Value == thumbprint).Any();
}
noteメモ
どちらのメソッドも、LINQ の簡単な構文に基づく同じ原理に従います。ターゲット タイプ "tenant" または "key" の要素をすべて選択し、入力値に一致するものが存在するかどうかを調べます。存在する場合、結果セットに対する Any() の呼び出しは true を返します。

最後に、次のような検証ロジックのオーバーライドを追加できます。

protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
    string issuerID = issuer.TrimEnd('/').Split('/').Last();

    if (ContainsTenant(issuerID))
    {
        if (ContainsKey(thumbprint))
            return true;
    }
    return false;
}

トークンを受信するとメソッドは WIF によって自動的に呼び出されます。ロジックは非常に単純であり、発行テナントがリストに存在すること、およびトークンが登録済みの証明書で署名されていることを検証します。

MultiTenantIssuerNameRegistry にはさらにメソッドを追加する必要がありますが、検証に関してはクラスには必要なものがすべて含まれます。

認証パイプラインの正しいステージでアクティブ化されるようにするには、既定の IssuerNameRegistry の代わりに Web.config に追加する必要があります。

Web.config ファイルを開き、<issuerNameRegistry> 要素を探し、以下に置き換えます。

<issuerNameRegistry type="ExpenseReport.AADUtils.MultiTenantIssuerNameRegistry, ExpenseReport" />

最初のチュートリアルでは、アプリケーションが起動するたびに発行者の調整 (トークンの署名を検証するために使用される X.509 証明書の発行者とサムプリント) を更新するロジックをアプリケーションに追加しました。詳細は「自動メタデータ更新の追加」を参照してください。

テナントとキーの情報を Web.config 以外のファイルに保存するようになったので、Application_Start() イベントでの更新の実行にバインドされなくなりました。ただし、これはアプリケーションのライフサイクルにおいて適切なタイミングなので、このチュートリアルではこのままにします。

ただし、いくつかの詳細に対処する必要があります。

  • ValidatingIssuerNameRegistry.WriteToConfig() メソッドは元の構成エントリで動作し、Web.config 内にあることが期待されます。このカスタム MTINR では動作しません。

  • 受け付けられるテナントのリストはテナントの単一のメタデータには含まれません。

どちらも簡単に解決できます。tenants.xml のキーを更新するだけの別の静的メソッドを MTINR に追加するだけです。対応する MultiTenantIssuerNameRegistry.cs ファイルの MultiTenantIssuerNameRegistry クラスに追加するメソッドのコードを次に示します。

public static void RefreshKeys(string metadataAddress)
{
    IssuingAuthority ia = 
           ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataAddress);

    bool newKeys = false;
    foreach (string thumbp in ia.Thumbprints)
        if (!ContainsKey(thumbp))
        {
            newKeys = true;
            break;
        }

    if (newKeys)
    {                
        XElement keysRoot = 
             (XElement)(from tt in doc.Descendants("keys") select tt).First();
        keysRoot.RemoveNodes();
        foreach (string thumbp in ia.Thumbprints)
        {
            XElement node = new XElement("key", new XAttribute("id", thumbp));
            keysRoot.Add(node);
        }
        doc.Save(filePath);           
    }
} 

このメソッドは 3 つのタスクに分けることができます。

  • ValidatingIssuerNameRegistry によって提供される静的メソッド GetIssuingAuthority() の呼び出しは、サービスによって提供される、受信トークンの検証に使用されるキーを、メタデータ ドキュメントから抽出します。

  • 最初の foreach ブロックは、メタデータ ドキュメントで見つかったキーが tenants.xml に既にあるかどうかを調べます。

  • メタデータに新しい情報が見つからなかった場合、メソッドを変更なしで終了します。見つかった場合は、現在の tenants.xml 内のキーをクリーンアップし、メタデータ ドキュメントの新しいものに置き換えます。

noteメモ
最初のチュートリアルの「自動メタデータ更新の追加」セクションで示されている HTTPS エンドポイントの検証に関する警告と同じことが、ここでも適用されます。

自動キー更新を実装するために必要なロジックはこれだけです。次のステップでは、Web.config ベースのルーチンの代わりに RefreshKeys を呼び出すように Global.asax を変更します。Global.asax を探し、RefreshValidationSettings を次のように変更します。

protected void RefreshValidationSettings()
{
    string metadataAddress = 
           ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
    AADUtils.MultiTenantIssuerNameRegistry.RefreshKeys(metadataAddress);
}
noteメモ
テナント独立エンドポイントに移行する代わりに、Windows Azure AD テナントのメタデータ アドレス (つまり、ID およびアクセス ツールの最初の実行によって取得された、最初に開発されたアプリケーションのテナントのもの) にまだ依存していることにお気付きかもしれません。実際、この 2 つはほぼ同等です。Azure AD でのアプリケーションのエントリはテナントに結び付けられているため、対応するメタデータ エンドポイントが機能することが保証されます。一方、テナント独立エンドポイントに移行すると、他のアプリケーションの起点としてコードの再利用が容易になります。どちらの方法を選択してもかまいませんが、チュートリアルでは必要なコード変更が最小のものを選択します。

クラシック LoB アプリケーションではすべてのユーザーは同じ機関ものなので、認証フローはいつでも認証済みユーザーの送り先を明確に決定できます。さらに、通常、ユーザーは機関とのアクティブなセッションを既に持っているので (ユーザーはローカル AD ドメインでワークステーション プロンプトから既にサインインしています)、認証フェーズは透過的に実行でき、ブラウザーでのアプリケーションのアドレスの入力と UI へのアクセスの間に中断はありません。これは、WS-Federation のようなサインオン プロトコルを使用するように構成されている Web アプリケーションの既定の動作です。

マルチテナント アプリケーションは、その名前のとおり、複数のテナントのユーザーによって使用されます。ユーザーは、ホーム領域検出 (HRD) と呼ばれる、認証にかかわる機関を確立するプロセスに参加するために呼び出されます。Azure AD では、このフェーズはテナント独立エンドポイントによって処理され、ユーザーに必要なエクスペリエンスをガイドします。そのためのコード変更は不要です。ただし、次の示すように、いくつか作業が必要な HRD 以外の部分があります。

多くの場合、マルチテナント アプリケーションには、匿名ユーザーが使用できるエクスペリエンスが含まれます。よくある例として、ランディング ページ、オンボード機能、ニュース、パブリック サポート フォーラム、無料お試し版へのエントリ ポイントなどがあります。包括的保護アプローチはこのような機能をサポートするには不適切です。ここでは、コントローラー単位のよりきめ細かい認証要件を適用するように WIF 設定を変更する方法を示します。

Web.config ファイルを変更する

  1. Web.config を開き、“Commented by Identity and Access VS Package” というコメント ブロックのすぐ下にある <system.web><authorization> 要素を探します。

    noteメモ
    <location> ブロックにある同じ名前の要素と間違えないでください。

  2. 現在の設定 <deny users="?" /> は、認証済みのユーザーに対してのみこのアプリケーションからのリソースの要求を許可する必要があることを ASP.NET に指示します。Web.config のこの制約は必要ないので、authorization 要素全体をコメント アウトします。

    <!--<authorization>
      <deny users="?" />
    </authorization>-->
    
    必要なのは、認証の処理方法を直接管理できるようにすることです。フォーム認証に戻すことによってこれを実現します。認証が必要なときは特定のアドレスにリダイレクトする必要があることを ASP.NET に指示します。そのアドレスに対する要求を新しいコントローラーで処理し、フェデレーション認証をトリガーします。

  3. Web.config<authentication> 要素を探してコメント化し、作成したコメント ブロックのすぐ下に次の要素を貼り付けます。

    <!--<authentication mode="None" />-->
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    
  4. <system.webServer> 要素までスクロール ダウンし、<modules> リストを探します。FormsAuthentication モジュールに対する <remove> ディレクティブがあります。次のようにそれをコメント化します。

    <modules>
          <!--<remove name="FormsAuthentication" />-->
    
  5. 最後に、Web.config の末尾までスクロール ダウンします。先に変更した <wsFederation> 要素で、passiveRedirectEnablefalse に設定します。

    <wsFederation passiveRedirectEnabled="false" 
    issuer="https://login.windows.net/common/wsfed" realm="https://<your-tenant-name>.onmicrosoft.com/ExpenseReport" requireHttps="false" />
    
    noteメモ
    既定では、WIF モジュールはアプリケーションからのすべての 401 リターン コードを調査し、正しく構成されている機関がある場合は、信頼できる機関にサインイン メッセージを伝達する 302 リダイレクトに変換します。この最後の設定は、代わりにフォーム認証の設定に従ってリダイレクトできるよう (この場合はカスタム コントローラーに対して)、送信 401 を無視するように WIF に指示します。

アカウント コントローラーを作成する

  1. アプリケーションは、認証時に ~/Account/LogOn にリダイレクトするように構成されています。その特定のルートを処理するコントローラーを作成しましょう。

    Controllers フォルダーを右クリックし、[追加] をクリックし、[コントローラーの追加] をクリックして、名前を AccountController に設定します。

  2. ディレクティブを使用して次のコードを追加します。

    using System.IdentityModel.Services;
    
  3. コントローラーの既定の実装を削除し、以下に置き換えます。

    public void LogOn()
    {
        RedirectResult result;
        if (!Request.IsAuthenticated)
        {
            SignInRequestMessage sirm = FederatedAuthentication.WSFederationAuthenticationModule.CreateSignInRequest("", HttpContext.Request.RawUrl, false);
            result = Redirect(sirm.RequestUrl.ToString());               
        }
        else
        {
            result = Redirect("~/");
        }
        result.ExecuteResult(this.ControllerContext);
    }
    
    

まとめ:コントローラーは、WIF モジュールによって実装された次のようなロジックを実行します。

  • 要求が認証済みでない場合:

    • 構成設定に従って WS-Federation サインイン メッセージを生成します (<wsFederation> 要素の内容)

    • ユーザーのブラウザーをリダイレクトします

  • 要求が認証済みの場合:

    • ホーム ページにリダイレクトします。

利点は、それが発生するときを完全に制御できることです。後で見るように、これによりアプリケーションの UI に明示的なサインオン ジェスチャを追加しながら、要求されたリソースの認証ポリシーによってトリガーされる自動リダイレクトを利用できます。

noteメモ
このチュートリアルでは最小限のアプローチを使用し、認証エクスペリエンスは Azure AD によって完全に処理されます。ただし、実際のソリューションでも同じアプローチを使用する必要があるわけではありません。認証フローがトリガーされたときに行うことを完全に制御できます。ユーザーに情報を要求する (または単にヘルプの) ビューを表示する場合は、LogOn アクションを変更するだけで簡単に行うことができます。

完全なフェデレーション認証フォーム認証統合を行うために最後に 1 つ行うことがあります。

保護されたリソースに対する要求への応答で LogOn アクションが呼び出されたとき、フォーム認証モジュールには ReturnUrl クエリ パラメーターに送信元リソースの URL が含まれます。しかし、WIF はそれを無視します。現状では、認証されたユーザーは要求されたリソースではなくアプリケーションのホーム ページに移動します。リソースへの追加の内部リダイレクトは簡単に実行できます。End_Request イベントの処理ロジックを Global.asax に追加するだけです。

  1. Global.asax を開いて以下のディレクティブを追加します。

    using System.Security.Claims;
    
  2. 次に、次のメソッドを追加します。

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        string wsFamRedirectLocation = HttpContext.Current.Response.RedirectLocation;
        if (wsFamRedirectLocation != null && 
            wsFamRedirectLocation.Contains("ReturnUrl") && 
            ClaimsPrincipal.Current.Identity.IsAuthenticated)
        {
            HttpContext.Current.Response.RedirectLocation =
                        HttpUtility.ParseQueryString(
                          wsFamRedirectLocation.Split('?')[1])["ReturnUrl"];
        }
    }
    

このメソッドは、HTTP 要求処理パイプラインの最後に実行します。HTTP ヘッダー Location を調査します。これはリダイレクトの場合に使用されます。空でなく、ユーザーが認証されいて (したがって、WS-Federation プロトコル フローは既に完全に実施されている)、ReturnUrl が含まれている (フォーム認証から返された情報を格納していることを示す) 場合、ブラウザーは ReturnUrl の場所にリダイレクトされます。

コントローラーを保護する

包括的認証保護をオフにしたので、すべてのコントローラーが認証要件を指定する必要があります。最も簡単な方法は、他の ASP.NET 認証シナリオと同じように、すべての Action を [Authorize] 属性で修飾することです。

Warning警告
チュートリアルは MVC スタイルのアプリケーションが対象ですが、Web フォームでも同じ用法を使用できます (たとえば、<location> および <authorization> 要素を Web.config で使用して)。

Home コントローラーの About() アクションに適用した変更を次に示します。

[Authorize]
public ActionResult About()
{
    ViewBag.Message = "Your app description page.";

    return View();
}

Home コントローラーのすべてのアクションに同じことを行いますが、Index() は例外です。 このチュートリアルでは、Index はアプリケーションのエクスペリエンスに対する非認証エントリ ポイントとして予約されています。

最初のチュートリアルでは、クレームからユーザー情報を抽出するように Index を変更しました。ここでは非認証ユーザーはアクションにアクセスでき、認証済みユーザーがいないことが使用できるクレームがないことを意味するのであれば、そのコードは失敗します。そのコメントを解除し、ViewBag.Message の割り当てを適当なメッセージに置き換えます。

Public ActionResult Index()
{
    //ClaimsPrincipal cp = ClaimsPrincipal.Current;
    //string fullname =
    //       string.Format(“{0} {1}”, cp.FindFirst(ClaimTypes.GivenName).Value,
    //       cp.FindFirst(ClaimTypes.Surname).Value);
    ViewBag.Message = "Welcome to the Expense Note App";
    return View();
}
noteメモ
チュートリアルではその方法を説明しませんが、必要にい応じて、ここに (または関連するビューに) ユーザーを歓迎するテキストやアプリケーションの使用方法を説明するテキストを追加できます。サインアップの部分は特に後で役に立ちます。

_Layout.cshtml ファイルでサインインのジェスチャを変更する

これまでに行った変更は、ユーザーが [Authorize] で保護されているアクションを要求する UI 要素をクリックすると直ちに認証フローをトリガーします。ただし、包括的保護によってカバーされていないアプリケーションがサインインに対する明示的な UI ジェスチャを提供するのは非常に一般的です。

そのためには、サインイン追加チュートリアルでサインアウトの追加方法を説明するときに使用した _Layout.cshtml で定義されている画面上部のユーザー グリーティング テキストに戻ります。 そのときはすべてのものを _Layout.cshtml 内にインライン化しましたが、このチュートリアルでは、他の機能とリファクタリングの呼び出しを追加する必要があります。

  1. _Layout.cshtml を開き、ログイン セクション <section id=”login”> を探して、次のように変更します。

    <section id=”login”>
       @Html.Partial("_LoginPartial")
       @* @if (Request.IsAuthenticated) 
        {                       
           <text> Hello, <span class=”username”>@User.Identity.Name</span>! @Html.ActionLink(“Signout”,”SignOut”, “SignOut”)</text>
        } 
        else {          
            <text>  You are not authenticated </text> 
         } *@
    </section>
    
    
  2. 終了後、Views/Shared フォルダーを右クリックし、[追加]、[ビュー] の順にクリックし、ビューの名前を _LoginPartial に設定し、ビュー エンジンとして Razor を選択して、[追加] をクリックします。

  3. _LoginPartial.cshtml の内容を次のコードに置き換えます。

    @if (Request.IsAuthenticated) 
        {                       
           <text> Hello, <span class=”username”>@User.Identity.Name</span>! @Html.ActionLink("Signout","SignOut", "SignOut")</text>
        } 
        else {          
             <ul>       
            <li>@Html.ActionLink("Sign in", "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "signLink" })</li>
        </ul> 
         }
    

これは LoB チュートリアルでインライン化したロジックとほとんど同じであり、唯一の違いは、“you are not authenticated” というテキストが、Account コントローラーの LogOn アクションをアクティブ化するクリック可能なリンクに置き換えられていることです。

サインアウト コントローラー

マルチテナントのケースにサインアウト ロジックを適用するために変更は必要ありません。コントローラーは既に、サインアウト フローに使用する発行者エンドポイントを Web.config から取得するように構成されています。つまり、チュートリアルの最初で適用したテナント独立エンドポイントに対する変更を自動的に取得します。

Graph アクセス ロジックをカスタマイズする

Graph API アクセス ロジックは既に、現在のユーザーを記述するクレームで受信した tenantID に基づいてリソース エンドポイントを構築するように設計されています。ですから、ユーザーが複数のテナントからアクセスし始めても動作し続けます。

noteメモ
これを可能にする Azure AD の機能の 1 つは、ClientId およびクライアント シークレットがテナントによって変化しないというものです。テナント管理者が、自分の Azure AD テナントにアプリケーションがアクセスすること同意を与えると、その管理者のテナントの対応する新しいアプリケーション エントリに、他のテナントと同じ値が設定されます。ただし、これは悪意のある管理者がアプリケーションのシークレットを取得して同じアプリケーションに同意した別の Azure AD テナントに対してそのシークレットを使用できるという意味ではないことに注意してください。Graph API のチュートリアルで学習したように、作成した後でシークレットを取得することはできません。

マルチテナントへの移行を完了するためにアプリケーションに追加する必要のある最後の機能は、新しい顧客組織を追加する機能です。

既に説明したように、Azure AD で外部使用可能とマークされたアプリケーションには特別に作成された URL が関連付けられます。見込み客はこの URL を使用して、アプリケーションによるディレクトリへのアクセスに同意し、テナントに自動的にプロビジョニングされたアプリケーションのエントリを取得できます。ここでは、ユーザーをリダイレクトできる SignUp コントローラーを同意 URL に追加し、アクションをトリガーするための UI ジェスチャを追加します。

noteメモ
ここでは機能をアプリケーションに直接追加しますが、アプリケーションの外部で同意ロジックを実装する方法を理解していれば、ポートフォリオ内の他のアプリケーションに対する同意リンクとグループ化できます。

  1. 既に説明したコントローラー作成方法に従って、空の SignUp コントローラーを追加します。

  2. ディレクティブを使用して次のコードを追加します。

    using System.Configuration;
    
    
  3. コントローラーの既定の実装を次の 2 つのメソッドに置き換えます。

    private string CreateConsentURL(string clientId, string requestedPermissions, 
                                    string consentReturnURL, string context)
    {
        string consentUrl = string.Format("https://account.activedirectory.windowsazure.com/Consent.aspx?ClientId={0}", clientId);
        if(!String.IsNullOrEmpty(requestedPermissions))
          consentUrl+= "&RequestedPermissions="+requestedPermissions;
        if(!String.IsNullOrEmpty(consentReturnURL))
            consentUrl+= "&ConsentReturnURL="+HttpUtility.UrlEncode(
                consentReturnURL+(String.IsNullOrEmpty(context) ?
                                         String.Empty : "?"+context ));
        return consentUrl;        
    }
    public void SignUp()
    {
        string request = System.Web.HttpContext.Current.Request.Url.ToString();
        string returnurl = request.Substring(0, request.Length -6);
        string clientID = ConfigurationManager.AppSettings["ClientId"];
    
        RedirectResult result = 
           Redirect(CreateConsentURL(clientID, "DirectoryReaders", returnurl, string.Empty));
        result.ExecuteResult(this.ControllerContext);
    } 
    
    

1 番目のメソッドは、見込み客がディレクトリ テナントにアクセスするための同意をアプリケーションに与えることができる URL を作成します。アプリケーションに対する同意 URL は Azure 管理ポータルによって提供されますが、基本パラメーターから URL を生成するコードを作成すると柔軟性を高めることができます。パラメーターとそのセマンティクスを説明します。

  • ClientId は、アプリケーションの ID を表します。Graph API のチュートリアルの間に構成に追加しました。これは必須です。

  • RequestedPermissions は、見込み客がアプリケーションに付与するディレクトリ アクセスのレベルを表します。使用可能な値は、アプリケーションの登録時に Azure 管理ポータルで選択したアクセス レベルを反映していますが、自身のテナントの UI で選択したものとは異なるレベルを自由に要求できます。値は次のとおりです。

    • DirectoryReaders: ディレクトリへの読み取りアクセスを要求するために使用します

    • DirectoryWriters: 読み取り/書き込みアクセスを要求するために使用します

    • <Empty>: SSO 機能だけを設定する場合は値を指定しません

  • ConsentReturnUrl は、ユーザーがアプリケーションへの権限を許可 (または拒否) した後でブラウザー セッションをリダイレクトする場所を示します。サインアップ処理ロジックが存在するアプリケーションのルートを指定します。後で詳述します。

CreateConsentURL メソッドは、前記のすべてのパラメーターに加えてさらに 1 つを公開します。コンテキスト パラメーターは追加情報を組み込む手段として提供されています。ConsentReturnUrl 内にエンコードされている同意ページに移動した後、リダイレクトが受け入れられると戻ります。メイン リターン URL とコンテキスト ロジックを混在させる必要がないように、別のパラメーターとして提供されています。

要求に関する追加情報を追跡する場合にコンテキストが便利です。たとえば、同意へのリダイレクトは独自のアプリケーション固有のオンボーディング プロセスの一部として非常に頻繁に実行され、一部のコンテキストを追跡したいことがあります。

2 番目のメソッドはリダイレクトをトリガーする実際のアクションです。CreateConsentURL を呼び出し、構成からの ClientId、リターン URL として現在のコントローラーのルート、要求されたアクセス レベルとして DirectoryReaders を渡し、コンテキストとしては何も渡しません。メソッドは新しく作成された URL にリダイレクトします。

同意 URL へのリダイレクトをトリガーするロジックを追加したので、結果を処理するコードを提供することによってフローを完成する必要があります。次の ReturnURL の選択によって確立されるように、このチュートリアルではそのコードを SignUp コントローラーの Index アクションに配置します。

  1. 次の using ディレクティブを追加します。

    using ExpenseReport.AADUtils;
    
  2. 次のメソッドを SignUp コントローラーに追加します。

    public void Index()
    {
        if ((!string.IsNullOrEmpty(Request.QueryString["TenantId"]) && 
            (!string.IsNullOrEmpty(Request.QueryString["Consent"]))))
        {
            if (Request.QueryString["Consent"].Equals("Granted",
                                                StringComparison.InvariantCultureIgnoreCase))
            {
                MultiTenantIssuerNameRegistry.AddTenant(Request.QueryString["TenantId"]);
            }
        
            //redirect to SignIn
            RedirectResult result = Redirect("~/Account/LogOn");
            result.ExecuteResult(this.ControllerContext);
        }
    }
    
    noteメモ
    このメソッド コードにはエラー管理は含まれません。

アクセスを許可または拒否すると、Azure AD は ReturnURL へのリダイレクトを受け入れて、2 つのパラメーターを追加します。

  • Consent: 操作の結果を示します。値は “Granted” または “Denied” です。

  • TenantID: Consent パラメーターの値が “Granted” の場合、TenantID が存在し、アプリケーションのアクセス要求に対して同意されたテナントの ID を含みます。

このメソッドの目的は、アプリケーションをプロビジョニングしたテナントの ID を取得し、MTINR コレクション内の有効な期間としてそれを追跡することです。先に作成した検証ロジックに従い、新しいテナントのユーザーがサインイン時に受け付けられるようにします。

前に示したコードは、要求 URL を調べ、新しいテナントが含まれる場合は、それを MTINR に保存します (後で実装するメソッドを使用)。

noteメモ
ここでの実装ではこのルートで到着する要求に対する制限は追加されず、形式が正しい場合は、TenantID パラメーターの内容が MTINR ストアに保存されます。実際のアプリケーションではこの動作は使用できません。悪用されてストアが不正エントリであふれたり、承認されていないアクセスを受け入れたりする可能性があるためです。

前述したように、同意エクスペリエンスは、独自のオンボーディング プロセスの一部になります (たとえば、見込み客についての情報の収集、支払いの受け取り、アプリケーションで必要な他のオンボーディング手順など)。そのため、そのコンテキストを同意 URL の作成に含め、応答を処理するときに検証する必要があります。それによって不正要求が拒否されます。

テナントを保存した後、メソッドはサインオンをトリガーし、ユーザーがすぐにアプリケーションへのアクセスを開始できるようにします。

noteメモ
オンボーディング プロセスでさらに手順が必要な場合は、サインオンを延期して、代わりにビューを提供できます。

SignUp コントローラーの Index アクションでは、新しい MTINR メソッド AddTenant を追加しました。その実装を追加します。MultiTenantIssuerNameRegistry.cs を開き、次のメソッドを MultiTenantIssuerNameRegistry クラスに追加します。

public static void AddTenant(string tenantId)
{
    if (!ContainsTenant(tenantId))
    {
        XElement node = new XElement("tenant", new XAttribute("id", tenantId));
        XElement tenantsRoot = 
                (XElement)(from tt in doc.Descendants("tenants") select tt).First();

        tenantsRoot.Add(node);
        doc.Save(filePath);
    }
}

AddTenant メソッドは非常に簡単です。入力の tenantId がストアにまだ存在しない場合 (同意操作はべき等です)、それに対する新しいエントリを <tenants> ノードに追加します。

最後に、アプリケーションにはサインアップ フローをトリガーする UI ジェスチャが必要です。これは、_LoginPartial.cshtml にエントリを追加することによって簡単に実現できます。ファイルを開き、サインアップの <li> ブロックを次のように変更します。

@if (Request.IsAuthenticated) 
    {                       
       <text> Hello, <span class="username">@User.Identity.Name</span>! @Html.ActionLink("Signout","SignOut", "SignOut")</text>
    } 
    else {          
         <ul>  
       <li>@Html.ActionLink("Sign up", "SignUp", "SignUp", routeValues: null, htmlAttributes: new { id = "signupLink" })</li>     
        <li>@Html.ActionLink("Sign in", "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "signLink" })</li>
    </ul> 
     }

noteメモ
現在の UI は最小限のものです。実際のアプリケーションでは、サインアップおよびサインイン コントロールのセマンティックを作成する必要があります。そのための方法としては、さらに詳細なリンク テキスト、ホーム ページのメイン本体での説明、その他があります。

ここでは、新しいマルチテナント アプリケーションではこの動作のテストに利用できるオプションを説明します。

マルチテナント アプリケーションのすべての側面をテストするには、サンプル アプリケーションのすべての同意関連フローを実行するために使用できる第 2 の Azure AD テナントを用意するのが最適です。この段階では、これは別の Azure サブスクリプションにアクセスできる必要があることを意味します。これを取得するには、最初のチュートリアルの開始時に説明したサインアップおよびディレクトリ作成フローを再度実行します。または、ここでの指示に従って、既存の Azure AD テナントのユーザーでトライアル サブスクリプションにサインアップします。

同意操作はべき等なので、テスト用にサインアップした独自の Azure AD テナントを使用することもできます。そうすれば第 2 のサブスクリプションの作成タスクを割愛できますが、プロビジョニングされていないテナントでサインインを試みるとき、または同意取り消しフローを実行するときに、何が起きるかを確認できません (テナントでアプリケーションがまた LoB アプリケーションではないために、同意許可手順の明確な必要性なしで明示的にプロビジョニングされている場合)。

もう 1 つのテスト方法は、Azure サブスクリプションに必ずしも関係のない Azure AD テナントを使用することです。たとえば、Office 365 や Intune などのサービスをサブスクライブするときに取得したディレクトリ テナントです。

noteメモ
Azure AD テナント管理者のみが、アプリケーションに同意を許可することができます。どのテスト方法を選択しても、テナント管理者ユーザー資格情報にアクセスできる必要があります。Live ID ベースの Azure サブスクリプションを使用して Azure AD テナントを作成した場合、グローバル管理者ロールに属するテナント ユーザーが少なくとも 1 人はテナントに含まれる必要があります。最初のチュートリアルの指示に従って簡単に作成できます。ユーザー プロファイル画面で必ず “グローバル管理者” を選択します。

動作するマルチテナント アプリケーションを確認できます。アプリケーションの内部動作を観察したい場合は、チュートリアルで追加したコード フラグメントに自由にブレークポイントを追加できます。

アプリケーションの実行

noteメモ
自身の Azure AD テナント以外のテナントを使用している場合は、開始する前にすべてのブラウザー インスタンスを閉じる必要があります。または、既定ではない別の Web ブラウザーでセッションのデバッグを開始するように Visual Studio に指示できます。これらの方法は、既存の Web セッションとデバッグ セッションの間に干渉がないようにするために必要です。

Visual Studio で F5 キーを押します。

アプリケーション ホーム ページ

認証のために Azure AD に直ちにリダイレクトされる代わりに、アプリケーションのホーム ルートが表示されます。

現在は認証されていないので、上部バーのログイン セクションに、サインアップおよびサインイン ボタンが正しく表示されます。

オンボーディング フローをテストします。サインアップ ボタンをクリックします。

AAD へのサインイン

Azure AD の認証プロンプトに直ちにリダイレクトされます。テストに使用する Azure AD テナントの管理者の資格情報を使用してサインインします。

アクセス権の付与

noteメモ
エラーが発生する場合は、Azure AD テナントの管理者としてサインインしていることを再確認してください。現在、Live ID ユーザーはここで説明するフローでの同意の許可に使用できません。

認証が正常に完了するとすぐに、SignUp コントローラーで指定されたアクセス レベルで Expense Reporting アプリケーションにディレクトリ テナントへのアクセスを許可または拒否することを求めるプロンプトが表示されます。

[許可] をクリックします。

アプリケーション ホーム ページ

同意したことが現在のユーザーのディレクトリに記録され、サインインがトリガーされます。同意時に Azure AD で既に認証されている場合は、資格情報を入力する必要はなく、自動的にサインインします。ログイン セクションに新しい状態が反映され、ユーザーの名前とサインアウト ボタンが表示されます。

アプリケーションのどこでもクリックして、認証済みセッションにいることを確認できます。たとえば、[ユーザー] タブをクリックすると、ユーザーの一覧が表示されます。

noteメモ
マルチテナント アプリケーションが、最近そのアプリケーションに同意した Windows AD テナント用の Graph API にアクセスするためのトークンを取得しようとすると、トークン要求が ACS50012 エラーで失敗する場合があります。この問題を解決するには、数分待ってからやり直してください。または、同意した後、同意を提供したテナント管理者がアプリケーションにログオンしてください。詳細については、「ACS エラー コード」を参照してください。

サインアウトをテストします。サインアウト ボタンをクリックします。

サインアウト

2、3 回リダイレクトされた後、[SignOut] ビューが表示されます。

本当にサインアウトしたことを確認するには、[ユーザー] タブを再びクリックします。今度はサインイン プロンプトが表示されます。

資格情報を入力します。認証フェーズのリダイレクトの後、最初の場所で要求されたユーザー UI がブラウザーに正しく表示されることを確認します。これは、End_Request イベントに追加したロジックが正しく動作していることを示します。

アクセス権の取り消し

このセクションで説明するタスクを実行できるのは、自身の Azure AD テナント以外のテナントでアプリケーションをプロビジョニングして、Azure サブスクリプションに関連付けた場合だけです。

Azure 管理ポータルに移動し、アプリケーションのプロビジョニングに使用した Azure AD テナントの管理者としてサインインします。

[Active Directory] タブに移動し、ディレクトリを選択し、[アプリケーション] を選択し、Expense Reporting アプリケーションを探してクリックします。

統合アプリケーションの詳細

アプリケーションが作成されたテナントの場合はアプリケーションの設定を変更できる構成 UI が表示されますが、ここではアプリケーションを購入した顧客になっています。メイン アプリケーションの調整と許可されているアクセス レベルが要約されている一般的な説明ページが表示されます。

下部コマンド バーの [アクセスの管理] ボタンをクリックします。

アクセスの管理

この UI を使用すると、許可された条件でディレクトリにアクセスできるようにしたくなくなった場合に、アプリケーションへのアクセスを取り消すことができます。

[削除] をクリックします。

アクセスが削除されました

アプリケーションが削除され、[アプリケーション] リストに表示されなくなります。

Visual Studio に戻り、F5 キーを再び押します。

[サインイン] をクリックして、顧客テナントの管理者として認証し、動作を確認します。

ACS50000 エラーです。

ディレクトリでのユーザー認証は成功しますが、認証トークンを受信するアプリケーションは、ユーザーのディレクトリ テナントにアクセスできるアプリケーションのリストには表示されません。その結果、ディレクトリは要求されたトークンを発行せず、ユーザーにエラー ページを表示します。

コミュニティの追加

表示:
© 2014 Microsoft