Web 用のクレーム ベースのシングル サインオン
この章では、単一のセキュリティ領域に属しているイントラネットとエクストラネットの Web ユーザーのためのシングル サインオン (SSO) の例について、順を追って説明します。ここでは、2 つの既存のクレーム対応アプリケーションの例を使用します。一方のアプリケーションはフォーム認証を使用し、もう一方のアプリケーションは Windows 認証を使用します。アプリケーションがクレーム ベースの認証を使用することで、アプリケーションとのやり取りを、社内ネットワークからも公開インターネットからも実現できることがわかります。
注意
SSO では、発行者は、複数のアプリケーションを使用するユーザーとのセッションも作成します。
この基本的なシナリオでは、企業間に信頼関係を確立する方法については触れません (「第 4 章「Web アプリケーション用のフェデレーション ID」」で説明されています)。ここでは、他のセキュリティ ドメインとリソースを共有する準備としてセキュリティ ドメイン内にシングル サインオンとシングル サインオフを実装する方法、および Microsoft® Windows® Azure にアプリケーションを移行する方法に焦点を合わせます。つまり、このシナリオには、すべてのクレーム対応アプリケーションで一般的に使用される要素が含まれます。
前提条件
Adatum は、社内ネットワークに Microsoft Active Directory® ディレクトリ サービスを使用して従業員を認証している中規模企業です。Adatum の営業部門は a-Order という Adatum の注文処理システムを使用して顧客注文を入力、処理、および管理しています。Adatum の従業員は、ビジネス関連経費の追跡と払い戻しのシステムである a-Expense も使用しています。
どちらのアプリケーションも、ASP.NET 3.5 を使用して構築され、Adatum のデータ センターに展開されています。図 1 に、a-Order と a-Expense の構造を表すホワイトボードの図を示します。
図 1
クレームを使用する前の Adatum のインフラストラクチャ
2 つのアプリケーションは、認証の処理方法が異なります。a-Order アプリケーションは、Windows 認証を使用します。このアプリケーションは、従業員が社内ネットワークにログオンする際に使用される資格情報を認識します。アプリケーションは、ユーザー名とパスワードの入力を求める必要がありません。a-Order は、Active Directory に保存されているグループから派生するロールを承認に使用します。a-Order は、これによって Adatum のインフラストラクチャに統合されています。
a-Expense のユーザー エクスペリエンスは、もう少し複雑です。a-Expense アプリケーションは、独自の認証、承認、およびユーザー プロファイル情報を使用します。このデータは、アプリケーション データベースのカスタム テーブルに保存されます。ユーザーは、アプリケーションを起動するたびに、Web フォームにユーザー名とパスワードを入力します。a-Expense アプリケーションの認証方法には、その経緯が反映されています。このアプリケーションは、Adatum の IT 部門以外で開発された人事管理プロジェクトとして始まりました。時間が経過するに従って、他の部門もこれを採用しました。現在は、Adatum の社内 IT ソリューションの一部になっています。
注意
フォームベース認証用のユーザー データベースを最新の状態に維持することは、データベースが Adatum の従業員のアカウント管理プロセスに統合されていないため、大きな負荷になっています。
a-Expense のアクセス コントロール ルールは、アプリケーション固有のロールを使用します。アクセス コントロールは、アプリケーションのビジネス ロジックと混在しています。
a-Expense が使用するユーザー プロファイル情報の一部は Active Directory 内にも存在しますが、a-Expense は社内エンタープライズ ディレクトリに統合されていないので、そこにはアクセスできません。たとえば、Active Directory には各従業員のコスト センターを示す情報が格納されていますが、これは a-Expense のユーザー プロファイル データベースでも維持されています。a-Expense でユーザーのコスト センターを変更する作業は、煩雑でエラーの原因になります。すべての従業員は、コスト センターが変更されると、各自のプロファイルを手動で更新する必要があります。
目標と要件
Adatum は、クレーム ベース ID ソリューションに移行する際に次のような目標を定めました。1 つ目の目標は、シングル サインオン機能をネットワークに追加することです。これにより、従業員は一度ログオンするだけで、a-Expense などの承認されているすべてのシステムにアクセスできるようになります。SSO を使用すると、ユーザーは a-Expense を使用する際にユーザー名とパスワードを入力する必要がなくなります。
注意
ID ソリューションの選択は、明確な目標と要件に基づいて行う必要があります。
2 つ目の目標は、Adatum の従業員がインターネットから社内アプリケーションにアクセスできるようにすることです。営業部門のメンバーは客先に出向くことが多いので、仮想プライベート ネットワーク (VPN) セッションを確立する手間をかけずに a-Expense と a-Order を使用できるようにする必要があります。
3 つ目の目標は、将来の計画を立てることです。Adatum は、企業の成長と変化に対応できる柔軟なソリューションを求めています。現時点では、Windows Azure などのクラウド環境に、いくつかのアプリケーションをホストできるアーキテクチャを実装することが優先課題です。運用をデータ センターの外部に移動すると、設備投資が軽減され、アプリケーションの管理が簡単になります。Adatum は、顧客が a-Order などのいくつかのアプリケーションにアクセスできるようにすることも考えています。Adatum は、これらの計画を実現するための基盤がクレーム ベースの ID とアクセス コントロールであることを認識しています。
注意
変化に対応することは、IT 運用の 1 つの課題です。
Adatum は、以上の目標を達成しながらエンタープライズ ディレクトリへのこれまでの投資をこのソリューションで再利用しようとしています。また、ユーザー ID が引き続き集中管理され、複数のストアに分散しないことも必要です。ただし、各事業部門が管理するデータへのアクセスは、それぞれが柔軟に制御できるようにします。たとえば、Adatum の全従業員に a-Expense アプリケーションを使用する権限を与える必要はありません。現在、プログラムへのアクセスは、アプリケーション固有のロールによって制御されており、これらのロールは各部署が管理するデータベースに格納されています。Adatum の ID ソリューションは、この柔軟性を確保する必要があります。
最後に、Adatum は、ID ソリューションが複数のプラットフォームとベンダーで動作することも求めています。さらに、Adatum もすべての企業と同様に、社内アプリケーションへのすべてのインターネット アクセスの安全を確保することが必要です。
以上の内容を考慮して、Adatum の技術スタッフは、クレーム ベースのシングル サインオンをサポートするために a-Expense アプリケーションと a-Order アプリケーションの両方を変更することを決定しました。
ソリューションの概要
最初の作業は、ID 情報のどの部分が社内全体で共有され、どの部分がアプリケーション固有かを分析することでした。重要なことは、ディレクトリ情報に対するこれまでの投資を最大限に活用することでした。確認すると、Active Directory ストアに既に必要な情報があることがわかりました。具体的には、エンタープライズ ディレクトリに、ユーザー名とパスワード、姓、名、電子メール アドレス、従業員のコスト センター、オフィス所在地、および電話番号が維持されていました。
注意
クレームは、既存のディレクトリ情報を活用できます。
この情報は既に Active Directory にあるので、クレーム ベース ID ソリューションでは、個々のアプリケーションに合わせて Active Directory スキーマを変更する必要はありません。
注意
Active Directory スキーマの変更は誰もが避けたいと考えます。アプリケーション固有のルールまたはクレームを Active Directory 以外のデータ ストアからクレーム発行者に追加する方が簡単です。
組織のクレーム発行者を導入することを変更の中心にするという決定が行われました。Adatum のアプリケーションは、この発行者を信頼してユーザーを認証します。
Adatum は、時間の経過と共に最終的にはすべてのアプリケーションが発行者を信頼することを想定しています。従業員に関する情報は企業の資産なので、最終的な目標は、カスタム従業員データベースを維持するアプリケーションがなくなることです。いくつかのアプリケーションには、エンタープライズ ディレクトリに移行しない (してはならない) 専用のユーザー プロファイル情報があることがわかっています。Adatum は、アプリケーション固有の属性を Active Directory ストアに追加せずに、できるだけ管理を分散することを求めています。
最初の展開では、Adatum は a-Expense と a-Order に集中することにしました。a-Order アプリケーションに必要とされることは、Active Directory のグループとユーザーをクレームとして使用するための構成の変更だけです。アプリケーションの構造や機能に直接的な違いはありませんが、この変更により、最終的に外部パートナーがアクセスできるようになります。
a-Expense アプリケーションは、アプリケーション固有のロール データベースを引き続き使用しますが、残りのユーザー属性は発行者が提供するクレームから取得されます。これにより、a-Expense ユーザーはシングル サインオンが可能になり、ユーザー ID の管理が合理化され、アプリケーションにインターネット経由でリモート アクセスできるようになります。
注意
段階的な作業が有効です。最初は、承認に影響を与えることなく認証の変更から開始できます。
注意
Adatum は、なぜ Windows 認証ではなく a-Expense のクレーム ベース ID を選択したのかという疑問があるかもしれません。Windows 認証もクレームと同様に SSO を提供し、ソリューションとしては、クレームを発行し、クレームを処理できるようにアプリケーションを構成するよりも簡単です。
その点は間違いありません。Windows 認証はイントラネット SSO との相性がきわめて優れているので、そのことが唯一の要件である場合は Windows 認証を使用してください。
ただし、Adatum の目標は単に SSO だけではありません。Adatum は、従業員が VPN 接続を使用することなく a-Expense と a-Order にリモート アクセスできることを求めています。Adatum は、a-Expense を Windows Azure に移し、最終的には顧客がインターネット経由で a-Order アプリケーションを使用して、処理中の注文を表示できるようになることも求めています。このシナリオには、クレーム ベースの手法が最適です。
図 2 に、技術スタッフが Adatum のホワイトボードに描いた提案を示します。この図には、内部ユーザーの認証方法が示されています。
図 2
クレーム ベース ID への移行
このクレーム ベースのアーキテクチャにより、Adatum の従業員はファイアウォールとプロキシを介してアプリケーションと発行者を発行するだけで、自宅で作業できます。図 3 に、Adatum の従業員が自宅から社内イントラネットを使用する方法を示します。
図 3
インターネット経由のクレーム ベース ID
注意
ADFS (Active Directory Federation Services) のプロキシ ロールは、インターネット クライアントとファイアウォールの背後の ADFS サーバーとの間の仲介サービスです。
発行者がユーザー名とパスワードの入力を求め、リモート ユーザーの ID を確立すると、従業員が企業のファイアウォールの内部にいる場合と同様に、同じクレームがアプリケーションに送信されます。
このソリューションにより、Adatum の認証方法ははるかに柔軟になります。たとえば、Adatum は、インターネットから接続する際にスマート カード、PIN、生体認証データなどの認証要件を追加することもできます。認証が発行者の責任になり、アプリケーションは常に同じクレームを受け取るので、アプリケーションを書き換える必要はありません。アプリケーションを変更することなくユーザーの認証方法を変更できることは、クレームの大きな利点です。
ここで提案されているアーキテクチャは、HTTP メッセージ ストリームの観点から見ることもできます。詳細については、第 2 章「クレーム ベースのアーキテクチャ」のメッセージ シーケンス図を参照してください。
実装の内部
ここでは、a-Expense をクレーム対応のアプリケーションに変更するプロセスを順を追って説明します。このセクションの途中で、https://claimsid.codeplex.com (英語) から 1SingleSignOn という Visual Studio® ソリューションをダウンロードすることもできます。このソリューションでは、a-Expense と a-Order について、クレームを含むバージョンと含まないバージョンを実装します。技術的な内容に関心がない場合は、次のセクションに進んでください。
注意
既定では、ダウンロード可能な実装はワークステーションでスタンドアロン実行されますが、多層環境に展開するように構成することもできます。
クレームを使用する前の a-Expense
クレームを使用する前の a-Expense アプリケーションは、フォーム認証を使用してユーザー ID を確立していました。クレーム対応のバージョンとの違いを理解するために、ここでフォーム認証のプロセスを簡単に再確認します。簡単に説明すると、フォーム認証は資格情報データベースとログオン ページへの HTTP リダイレクトで構成されます。
注意
Cookie はサーバー側から見て拡張性が高いので、多くの Web アプリケーションでは、ユーザー プロファイル情報をセッション状態ではなく Cookie に格納します。a-Expense は部署で使用するアプリケーションなので、拡張性は問題ではありませんでした。
図 4 に、フォーム認証を使用する a-Expense アプリケーションを示します。
図 4
フォーム認証を使用する a-Expense
注意
a-Order はセッション状態を使用しますが、Cookie はサーバー側から見て拡張性があります。a-Order は、同時に使用するユーザー数が少ない部署で使用するアプリケーションです。
a-Expense のログオン ページには、次の 2 つの目的があります。このページは、資格情報を要求してユーザーを認証し、パスワードのデータベースを使用してそれをチェックし、後から使用するときのために ASP.NET のセッション状態オブジェクトにアプリケーション固有のユーザー プロファイル情報をコピーします。プロファイル情報の例としては、ユーザーのフル ネーム、コスト センター、割り当てられているロールがあります。a-Expense アプリケーションは、ユーザー プロファイル情報をユーザーのパスワードと同じデータベースに保存します。これは、フォーム認証を使用するアプリケーションで広く行われています。
注意
a-Expense は、認証、承認、およびプロファイルに Membership、Roles、および Profile の各プロバイダーを使用する代わりに、カスタム コードを意図的に使用します。これは、ASP.NET 2.0 以前のバージョンで記述されたアプリケーションで広く行われます。
ASP.NET におけるフォーム認証を Web アプリケーションに追加する作業には、次の 3 つの部分があります。フォーム認証を行うためのアプリケーションの Web.config ファイル内の注釈、資格情報の入力を求めるログオン ページ、およびアプリケーション データに対して資格情報を検証するためのハンドラー メソッドです。次に、この 3 つの部分の動作を示します。
a-Expense の Web.config ファイルは、以下の XML 宣言を使用してフォーム認証を行います。
<authentication mode="Forms">
<forms loginUrl="~/login.aspx"
requireSSL="true" ... />
</authentication>
<authorization>
<deny users="?" />
</authorization>
authentication要素は、認証されないすべてのページ要求を指定されたログイン URL に自動的にリダイレクトするように、ASP.NET ランタイムまたはインターネット インフォメーション サービス (IIS) 7.0 (この両方が ASP.NET 統合モードとクラシック モードで実行されている場合) に指示します。認証されないユーザー (特別な記号 "?" で表されます) のアクセスを拒否する authorization要素も、このリダイレクトを行うために必要です。
次に、a-Expense に組み込み ASP.NET Login コントロールを使用する Login.aspx ページがあることがわかります。次にコードを示します。
<asp:Login ID="Login1" runat="server"
OnAuthenticate="Login1OnAuthenticate" ... >
</asp:Login>
最後に、アプリケーションを確認すると、Login.aspx ページの OnAuthenticateイベントのハンドラーが次のようになっていることがわかります。
public partial class Login : System.Web.UI.Page
{
protected void Login1OnAuthenticate(object sender,
AuthenticateEventArgs e)
{
var repository = new UserRepository();
if (!repository.ValidateUser(this.Login1.UserName,
this.Login1.Password))
{
e.Authenticated = false;
return;
}
var user = repository.GetUser(this.Login1.UserName);
if (user != null)
{
Session["LoggedUser"] = user;
e.Authenticated = true;
}
}
}
このロジックは、ログオン ページに広く使用されています。コードから、ユーザー名とパスワードが最初にチェックされることがわかります。資格情報が検証されると、ユーザー プロファイル情報が取得されて、LoggedUserキーの下のセッション状態に格納されます。データベースとのやり取りの詳細は、アプリケーションの UserRepositoryクラスの内部に置かれています。
AuthenticatedEventArgs オブジェクトの Authenticated プロパティを trueに設定すると、認証されたことが通知されます。ASP.NET は、要求を元のページにリダイレクトします。
この時点で、ページの Page_Loadメソッドが実行されて通常のページ処理が再開されます。a-Expense アプリケーションでは、このメソッドはセッション状態オブジェクトに保存されていたユーザーのプロファイル情報を取得し、ページのコントロールを初期化します。たとえば、次のようなロジックになります。
protected void Page_Load(object sender, EventArgs e)
{
var user = (User)Session["LoggedUser"];
var repository = new ExpenseRepository();
var expenses = repository.GetExpenses(user.Id);
this.MyExpensesGridView.DataSource = expenses;
this.DataBind();
}
セッション オブジェクトには、アクセス コントロールの決定を行うために必要な情報が含まれます。コードを見ると、a-Expense がアプリケーションで定義された AuthorizedRolesプロパティを使用して、どのようにこの決定を行っているかを確認できます。
クレームを使用する a-Expense
開発者は、a-Expense にいくつかの変更を加えるだけで、フォーム認証をクレームに置き換えることができます。資格情報を検証するプロセスは、ログオン ページを削除し、ASP.NET パイプラインに WIF (Windows Identity Foundation) の WSFederationAuthenticationModuleを含めるように構成するだけで、クレーム発行者に委任されました。このモジュールは、認証されないユーザーを検出し、それを発行者にリダイレクトして、クレームを含むトークンを取得します。ログオン ページはありませんが、アプリケーションはセッション状態オブジェクトにプロファイルと承認データを記述する必要があります。これは、Session_Startメソッドで行われます。この 2 つの変更で作業は完了します。
注意
アプリケーションをクレーム対応にするには、いくつかの変更を加えるだけです。
図 5 に、クレームに対応した a-Expense の認証プロセスを示します。
クレーム処理を含む a-Expense
図 5
クレーム処理を含む a-Expense
a-Expense のクレーム対応バージョンの Web.config ファイルには、WIF が提供するモジュールへの参照が含まれます。この Web.config ファイルは、FedUtil ウィザードを実行することによって自動的に変更されます。これには、コマンドライン (FedUtil.exe) を使用するか、Visual Studio で Web プロジェクトを右クリックして [STS 参照の追加] コマンドを実行します。
注意
WIF の FedUtil.exe ユーティリティを使用すると、簡単に a-Expense でクレームを使用できるようになります。「付録 A」を参照してください。
変更された Web.config ファイルを確認すると、承認セクションと認証セクションが変更されていることと、新しい構成セクションがあることがわかります。構成セクションには、発行者に接続するために必要な情報が含まれます。たとえば、発行者の URI (Uniform Resource Indicator) および証明書の署名に関する情報などが含まれます。
注意
ここでは、要点だけを示しています。WIF と ADFS の製品ドキュメントも参考になります。
Web.config ファイルで最初に気付くことは、認証されるユーザーへの要求はそのままで、認証モードが None に設定されていることです。
<authentication mode="None" />
<authorization>
<deny users="?" />
</authorization>
注意
これは多少奇妙に見えます。これが意味することは、認証処理が HTTP パイプラインの別の部分に移動されたということです。
注意
a-Expense が前に使用していたフォーム認証モジュールは、認証モード属性を Noneに設定することで無効化されています。代わりに、WSFederationAuthenticationModule(FAM) と SessionAuthenticationModule (SAM) が認証プロセスを担当します。
アプリケーションの Login.aspx ページは不要になったので、アプリケーションから削除できます。
次に示すように、Web.config ファイルには 2 つの新しいモジュールがあることがわかります。
<httpModules>
...
<add name="WSFederationAuthenticationModule"
type="Microsoft.IdentityModel.Web.
WSFederationAuthenticationModule, ..." />
<add name="SessionAuthenticationModule"
type="Microsoft.IdentityModel.Web.
SessionAuthenticationModule, ..." />
</httpModules>
読み込まれたモジュールは、ASP.NET 処理パイプラインに挿入されます。これは、認証されない要求を発行者にリダイレクトし、発行者から返された返信を処理し、発行者から受け取ったユーザー トークンを ClaimsPrincipalオブジェクトに変換するためです。これらのモジュールは、アプリケーションがアクセスできるように、ClaimsPrincipalオブジェクトに HttpContext.Userプロパティの値を設定します。
WSFederationAuthenticationModuleは、ユーザーを発行者のログオン ページにリダイレクトします。さらに、返されたセキュリティ トークンを解析して検証します。このモジュールは、ログオン プロセスの繰り返しを避けるために、暗号化された Cookie を書き込みます。SessionAuthenticationModuleはログオン Cookie を検出して解読し、ClaimsPrincipalオブジェクトに再入力します。
注意
ClaimsPrincipalオブジェクトは、既に説明した IPrincipalインターフェイスを実装します。これにより、既存のアプリケーションを容易に変換できます。
Web.config ファイルには、WIF 環境を初期化する Microsoft.IdentityModelのための新しいセクションがあります。
<configSections>
...
<section name="microsoft.identityModel"
type="Microsoft.IdentityModel.Configuration.
MicrosoftIdentityModelSection,
Microsoft.IdentityModel, ..." />
</configSections>
ID モデルのセクションには、発行者のアドレス、発行者との通信に必要な証明書 (serviceCertificate 要素と trustedIssuers 要素) など、WIF が必要とする数種類の情報が含まれます。
<microsoft.identityModel>
<service>
<audienceUris>
<add value=
"https://{adatum hostname}/ a-expense.claimsAware/"
/>
</audienceUris>
...
注意
"adatum hostname" の値は、サンプル コードを展開する場所によって異なります。開発環境では、"localhost" です。
セキュリティ トークンには、対象ユーザーの URI が含まれます。これは、発行者が特定の "audience" (アプリケーション) にトークンを発行したことを示します。一方、アプリケーションは、受信したトークンが実際にそこから発行されているかどうかをチェックします。audienceUris要素には、指定可能な URI の一覧が含まれます。対象ユーザーの URI を制限すると、アクセスが許可されていない別のアプリケーションのトークンが悪意のあるクライアントによって再利用されることを防止できます。
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true"
issuer="https://{adatum host}/{issuer endpoint} "
realm="https://{adatum host}/a-Expense.ClaimsAware/"
requireHttps="true" />
<cookieHandler requireSsl="true" />
</federatedAuthentication>
federatedAuthenticationセクションでは、発行者およびそれと通信するために必要なプロトコルを指定します。
注意
HTTPS を使用すると、MITM (Man-In-The-Middle) 攻撃と再生攻撃を防止できます。これは開発時に任意で指定できますが、運用環境では必ず HTTPS を使用してください。
<serviceCertificate>
<certificateReference x509FindType="FindBySubjectDistinguishedName"
findValue="CN=adatum" storeLocation="LocalMachine" storeName="My" />
</serviceCertificate>
サービス証明書セクションでは、トークンが暗号化されている場合に解読に使用する証明書の場所を示します。トークンの暗号化は任意で、発行者が決定します。HTTPS を使用する場合、トークンの暗号化は不要ですが、暗号化することはセキュリティのベスト プラクティスとして一般的に推奨されます。
<issuerNameRegistry
type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry,
Microsoft.IdentityModel, ... >
<trustedIssuers>
<add thumbprint="0E2A9EB75F1AFC321790407FA4B130E0E4E223E2"
name="CN=adatum" />
</trustedIssuers>
</issuerNameRegistry>
拇印は、X.509 証明書の署名をハッシュした結果です。SHA-1 は、それを行うための一般的なアルゴリズムです。拇印は、証明書と発行者を一意に識別します。issuerNameRegistry要素には、発行者が信頼する拇印の一覧が含まれます。発行者は、署名された X.509 証明書の拇印によって識別されます。拇印が受信トークンの署名に埋め込まれた証明書に一致しない場合、WIF は例外をスローします。拇印が一致すると、name属性が Claim.Issuerプロパティにマップされます。
このコード例では、フェデレートされたユーザー名を a-Expense アプリケーションがロール データベースに格納するので、このシナリオでは名前属性 adatumが必要です。フェデレートされたユーザー名の形式は、adatum\usernameです。
次の手順では、特定の証明書の拇印を探す方法を示します。
拇印を見つけるには
- タスク バーの [スタート] ボタンをクリックし、検索ボックスに「mmc」と入力します。
- mmc をクリックします。Microsoft 管理コンソール アプリケーションを含むウィンドウが表示されます。
- [ファイル] メニューで、[スナップインの追加と削除] をクリックします。
- [スナップインの追加と削除] ダイアログ ボックスで、[証明書] をクリックし、[追加] をクリックします。
- [証明書スナップイン] ダイアログ ボックスで、[コンピューター アカウント] を選択し、[次へ] をクリックします。
- [コンピューターの選択] ダイアログ ボックスで、[ローカル コンピューター] をクリックします。次に、[完了] をクリックし、[OK] をクリックします。
- 左のウィンドウに、コンピューターのすべての証明書のツリーが表示されます。必要に応じてツリーを展開します。Personal フォルダーを展開します。Certificates フォルダーを展開します。
- 拇印を取得する証明書をクリックします。
- [証明書の情報] ダイアログ ボックスで、[詳細] タブをクリックし、目的の拇印が表示されるまで下にスクロールします。
これで作業が完了しました。Web.config ファイルの変更により、認証が発行者に委任されます。
注意
構成する項目が多いように見えますが、FedUtil ウィザードによって処理されます。
ただし、まだ作業が必要な詳細項目が 1 つあります。前のセクションでは、セッション状態オブジェクトにユーザー プロファイル データを格納するためにログオン ハンドラーも使用していました (現時点ではアプリケーションから削除されています)。このロジック部分は、Global.asax ファイルにある Session_Startメソッドに移動されました。Session_Startメソッドは、新しいセッションが始まって認証が行われた後に ASP.NET によって自動的に呼び出されます。ユーザー ID は、スレッドの CurrentPrincipalプロパティによってアクセスされるクレームとして格納されます。Session_Startメソッドは、次のようになります。
protected void Session_Start(object sender, EventArgs e)
{
if (this.Context.User.Identity.IsAuthenticated)
{
string issuer =
ClaimHelper.GetCurrentUserClaim(
System.IdentityModel.Claims.ClaimTypes.Name).
OriginalIssuer;
string givenName =
ClaimHelper.GetCurrentUserClaim(
WSIdentityConstants.ClaimTypes.GivenName).Value;
string surname =
ClaimHelper.GetCurrentUserClaim(
WSIdentityConstants.ClaimTypes.Surname).Value;
string costCenter =
ClaimHelper.GetCurrentUserClaim(
Adatum.ClaimTypes.CostCenter).Value;
var repository = new UserRepository();
string federatedUsername =
GetFederatedUserName(issuer, identity.Name);
var user = repository.GetUser(federatedUsername);
user.CostCenter = costCenter;
user.FullName = givenName + " " + surname;
this.Context.Session["LoggedUser"] = user;
}
}
認証は発行者によって既に実行されているので、アプリケーションは、ユーザー認証のためにアプリケーションのデータ ストアにアクセスしないことに注意してください。WIF モジュールは、発行者が送信するセキュリティ トークンを自動的に読み込み、スレッドの現在のプリンシパル オブジェクトにユーザー情報を設定します。これで、ユーザーの名前などの属性は、現在のセキュリティ コンテキストで使用できるクレームになりました。
注意
一般的に、名前やコスト センターなどのグローバルに重要なデータはクレームに保存し、アプリケーション固有の属性はローカル ストアに保存します。
ユーザー プロファイルのデータベースは、現在のユーザーに適用されるアプリケーション固有のロールを格納するために a-Expense が引き続き使用します。実際、a-Expense のアクセス コントロールは、クレームを使用するかどうかに関係なく、変更はありません。
前のコード例は、ClaimHelperというヘルパー クラスのメソッドを呼び出します。これらのメソッドの 1 つ (GetCurrentUserClaim メソッド) は、現在のコンテキストで適用されるクレームを問い合わせます。このクエリを実行するには、次の手順を実行する必要があります。
System.Threading.Thread クラスの静的な CurrentPrincipalプロパティを取得することで、現在のユーザーのコンテキスト情報を取得します。このオブジェクトには、IPrincipalというランタイム型があります。
ランタイム型の変換を使用して、現在のプリンシパル オブジェクトを IPrincipal 型から IClaimsPrincipal 型に変換します。a-Expense はクレーム対応アプリケーションになっているので、実行時変換は正常に動作します。
IClaimsPrincipal インターフェイスの Identitiesプロパティを使用して、前の手順のクレーム プリンシパル オブジェクトに適用される ID のコレクションを取得します。返されるオブジェクトは、ClaimsIdentityCollectionクラスのインスタンスです。a-Expense アプリケーションでは使用されていない機能ですが、1 つのクレーム プリンシパルに複数の ID を含めることができます。
コレクションの最初の ID を取得します。そのためには、インデックスとしてコレクションのインデクサー プロパティに 0 を指定して使用します。このルックアップによって返されるオブジェクトは、現在のユーザーのクレーム ベース ID です。オブジェクトの型は IClaimsIdentity です。
IClaimsIdentity インターフェイスの Claimsプロパティを使用して、クレーム ID オブジェクトからクレーム コレクション オブジェクトを取得します。返されるオブジェクトは、ClaimsCollectionクラスのインスタンスです。これは、前の手順で得られたクレーム ID オブジェクトに適用されるクレーム セットを表します。
この時点で、クレーム コレクションを反復処理すると、探しているクレーム タイプに一致するクレームを選択できます。次に、それを実行するための式の例を示します。
claims.Single(c => c.ClaimType == claimType)
Singleメソッドは、要求されたクレーム タイプに一致するクレームが 1 つあることを前提にしています。目的のクレーム タイプに一致するクレームが複数あるか、または一致候補が見つからない場合、このメソッドは例外をスローします。Singleメソッドは、Claimクラスのインスタンスを返します。
最後に、Claim クラスの Valueプロパティを使用してクレームの値を抽出します。クレームの値は、文字列です。
注意
現在のユーザーのクレームを取得する方法の例として、サンプル コードの ClaimHelperクラスの実装を確認してください。
クレームを使用する前の a-Order
a-Expense とは異なり、a-Order アプリケーションは Windows 認証を使用します。これには、簡単であることも含めて多くの利点があります。
Windows 認証を有効にすることは、次のように XML に属性値を設定することと同じように簡単です。
<authentication mode="Windows" />
a-Order アプリケーションのアクセス コントロールの方法は、a-Expense よりもはるかに簡単です。認証ロジックとビジネス ルールを組み合わせる代わりに、a-Order は単純に Web.config ファイルのロールを使用してページに注釈を付けます。
<authorization>
<allow roles="Employee, Order Approver" />
<deny users="?" />
</authorization>
a-Order アプリケーションのユーザー インターフェイスは、ユーザーの現在のロールによって異なります。
base.OnInit(e);
this.OrdersGrid.Visible =
!this.User.IsInRole("Order approver");
this.OrdersGridForApprovers.Visible =
this.User.IsInRole("Order approver");
クレームを使用する a-Order
a-Order へのクレームの追加は、構成の変更だけで対応できます。アプリケーション コードへの変更は不要です。
注意
Windows 認証をクレームに変換するには、構成を変更するだけで済みます。
https://claimsid.codeplex.com (英語)からプロジェクトをダウンロードすると、クレームに変換する前後の Web.config ファイルを比較できます。Visual Studio でプロジェクトを右クリックし、[STS 参照の追加] をクリックするだけです。このプロセスは、前のセクションの a-Expense アプリケーションのプロセスとほとんど同じです。
必要なクレーム タイプは、前に Windows 認証が提供していたユーザーおよびロールと同じです。
<claimTypeRequired>
<claimType type=
"https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
/>
<claimType type=
"https://schemas.microsoft.com/ws/2008/06/identity/claims/role"
/>
</claimTypeRequired>
注意
指定されたクレーム タイプに複数の値が存在する場合もあることに注意してください。たとえば、1 つの ID が複数のロール クレームを持つこともできます。
アプリケーションからのサインアウト
WIF によって FederatedPassiveSignInStatusコントロールが提供されています。これを使用することで、シングル サインオンのシナリオでアプリケーションからサインアウトする方法を示します。
<idfx:FederatedPassiveSignInStatus
ID="FederatedPassiveSignInStatus1"
runat="server"
OnSignedOut="FederatedPassiveSignInStatus1SignedOut"
SignOutText="Logout"
FederatedPassiveSignOut="true"
SignOutAction="FederatedPassiveSignOut" />
idfxプレフィックスは、コントロールが Microsoft.IdentityModel.Web.Controls名前空間に属していることを示します。このコントロールにより、ブラウザーは ADFS 発行者にリダイレクトされ、そこでユーザーがログアウトされ、セッションに関連する Cookie が破壊されます。
セットアップと物理展開
クレーム対応 Web アプリケーションの展開では、クレーム対応ではない Web アプリケーションに関して既に説明した多くの手順が共通しています。違いは、発行者に関する特別な考慮です。この考慮事項としては、開発に適したテスト環境の提供、実稼動発行者への移行、発行者と Web アプリケーションがインターネット アクセスに対して適切に構成されていることなどがあります。
モック発行者の使用
a-Expense と a-Order のダウンロード可能バージョンは、既定で、スタンドアロン開発ワークステーションで動作するようにセットアップされます。これは、各自の環境でアプリケーションを開発する方法に似ています。一般的に、単一の開発マシンから始める方が簡単です。
注意
モック発行者を使用すると、開発プロセスが簡単になります。
これを利用するために、a-Expense と a-Order の開発者は発行者の小さなスタブ実装を記述しました。Visual Studio ソリューションをダウンロードすると、次のようなコードが含まれています。https://localhost/adatum.SimulatedIssuer という URL を使用してプロジェクトを見つけてください。
a-Expense アプリケーションと a-Order アプリケーションを初めて実行すると、これらが代替の発行者と通信することを確認できます。発行者は、事前に作成されたクレームを発行します。
注意
開発者の作成した簡単なクレーム発行者を使用することは、開発および単体テストにおける有効な手段です。受け入れテストと展開の段階に入ると、ネットワーク管理者の支援の下で、運用インフラストラクチャ コンポーネントを使用するようにアプリケーション構成を変更します。
そのようなコンポーネントを記述することはそれほど困難ではなく、オンライン サンプルを再利用することもできます。
Active Directory の隔離
a-Order アプリケーションは、Windows 認証を使用します。開発者は自社のエンタープライズ ディレクトリの ID を管理しないので、アプリケーション開発中は Active Directory をスタブと切り替えることが有効な場合もあります。
この例は、クレームを使用する前の a-Order アプリケーションで示されています。この手法を使用するには、Windows 認証を無効にし、セッション認証パイプラインにフックを追加し、選択したユーザー ID を挿入するように Web.config ファイルを少し変更する必要があります。Web.config ファイルを次のように変更して、Windows 認証を無効にします。
<authentication mode="None" />
Global.asax ファイルには、プログラマーが指定する ID によって ID を設定するコードを含める必要があります。次に例を示します。
<script runat="server">
void Application_AuthenticateRequest(object sender, EventArgs e)
{
this.Context.User = MaryMay;
}
private static IPrincipal MaryMay
{
get
{
IIdentity identity = new GenericIdentity("mary");
string[] roles = { "Employee", "Order Approver" };
return new GenericPrincipal(identity, roles);
}
}
</script>
このコードは、アプリケーションを展開する前に削除してください。
実稼動発行者への変更
運用環境に展開する準備ができたら、開発ワークステーションで動作するシミュレートされた発行者から、ADFS 2.0 などのコンポーネントに移行する必要があります。
注意
アプリケーションを展開するときは、モック発行者を削除してください。
この変更には、次の 2 つの手順が必要です。まず、FedUtil を使用して、実稼動発行者をポイントするように Web アプリケーションの Web.config ファイルを変更します。次に、Web アプリケーションからの要求を認識して適切なクレームを提供するように、発行者を構成します。
このガイドの「付録 A」では、FedUtil を使用するプロセスおよび Web.config ファイルを変更する方法について説明しています。
証明書利用者とクレーム ルールを追加する方法については、実稼動発行者が提供するドキュメントを参照してください。このガイドに含まれるサンプルの手順は、https://claimsid.codeplex.com (英語) にあります。
インターネット アクセスの有効化
認証を発行者に外部委託する利点の 1 つは、既存のアプリケーションに外部のインターネットから簡単にアクセスできることです。クレーム ベース ID のプロトコルは、インターネットに対応しています。この場合に必要なことは、アプリケーションと発行者を外部からアドレス指定できるようにすることだけです。VPN は不要です。
企業のファイアウォールの外部で展開する場合、Web アプリケーションと発行者を実行するホストには、証明機関から発行された証明書が必要です。各 URL は、完全修飾ホスト名または静的 IP アドレスを使用して構成する必要があります。ADFS 2.0 プロキシ ロールは、インターネットにおけるエンドポイントの公開をサポートします。
バリエーション — Windows Azure への移行
Adatum の計画の最終段階は、a-Expense を Windows Azure に移行することです。Windows Azure は、マイクロソフトのデータ センターを使用することで、インターネットで Web アプリケーションをホスティング、拡張、および管理できるオンデマンドのコンピューティング サービスとストレージを提供します。このバリエーションは、クレーム ベースの方法が持つ力と柔軟性を示します。a-Expense のコードには、まったく変更はありません。Web.config ファイルを編集する必要があるだけです。
注意
クレーム対応アプリケーションを Windows Azure に移動することは簡単です。
図 6 に、Adatum のソリューションの概要を示します。
図 6
Windows Azure 内の a-Expense
Adatum ユーザーの観点としては、Azure に移行するとアプリケーションの URL が変わる場合があることを除いて、a-Expense アプリケーションの場所は意味を持ちません。さらに、これも Windows Azure の URL に CNAME をマップすることによって対処できます。それ以外の動作は、Adatum のサーバー上にある場合と同じです。つまり、イベントのシーケンスは、a-Expense がクレーム対応になったときと同じです。ユーザーは、初めてアプリケーションにアクセスするときは認証されないので、WIF モジュールは構成されている発行者 (この場合は、Adatum の発行者) にユーザーをリダイレクトします。
発行者は、ユーザーを認証し、その後にユーザー名とコスト センターなど、a-Expense が必要とするクレームを含むトークンを発行します。次に、発行者は、セッションが確立された元のアプリケーションにユーザーをリダイレクトします。発行者はインターネット上にありますが、a-Expense は発行者が Adatum イントラネットにあったときと同じクレームを必要とします。
当然、Azure 内のアプリケーションを使用するすべてのユーザーが各自のコンピューターから発行者にアクセスできる必要があります。このシナリオでは、DNS サーバー、ファイアウォール、および従業員のインターネット アクセスを許可するように構成されたプロキシを含む Adatum のネットワークを前提にしています。
ただし、発行者は、外部リソースから使用できるようになる必要はありません。a-Expense アプリケーションが発行者と直接通信することはありません。代わりに、ブラウザーのリダイレクションを使用し、パッシブ クライアントのプロトコルに従います。このプロトコルの詳細については、「第 2 章「クレーム ベースのアーキテクチャ」」と「付録 B」を参照してください。
Windows Azure に a-Expense をホストする
次の手順では、Windows Azure にアップロードする証明書を構成し、Web.config ファイルに必要な変更を行う方法を説明します。これらの手順は、Windows Azure のトークンを既に取得していることを前提にしています。まだ取得していない場合は、https://www.microsoft.com/japan/windowsazure/getstarted/を参照してその方法を確認してください。
証明書を構成するには
- Visual Studio で、expense.cloud などの Azure プロジェクトを開きます。a-Expense.ClaimsAware ロールを右クリックし、[プロパティ] をクリックします。
- 証明書の拇印が必要な場合は、[証明書] をクリックします。他の情報と共に拇印が表示されます。
- [エンドポイント] をクリックし、[HTTPS] を選択します。[名前] フィールドを「HttpsIn」に設定します。[ポート] フィールドに、使用するポート番号を設定します。既定値は 443 です。[SSL 証明書名] ドロップダウン ボックスの一覧から、証明書名を選択します。既定値は localhost です。この名前は、[証明書] タブに表示されている名前と同じにする必要があります。
アップロードされる証明書は、トークンの暗号化ではなく SSL だけに使用されることに注意してください。Adatum から取得される証明書は、トークンを暗号化する必要がある場合にのみ必要です。
注意
Windows Azure と WIF は、どちらもトークンを解読できます。Windows Azure ポータルに証明書をアップロードし、新しいインスタンスが生成されるたびに証明書ストアに展開するように Web ロールを構成する必要があります。WIF の セクションは、展開された証明書をポイントする必要があります。
次に、Windows Azure に a-Expense アプリケーションを発行する手順を示します。
Windows Azure に a-Expense を発行するには
Microsoft Visual Studio 2008 で、a-expense.cloud ソリューションを開きます。
Windows Azure プロジェクトに localhost.pfx 証明書をアップロードします。証明書は、[samples-installation-directory]\Setup\DependencyChecker\certs\localhost.pfx に読み込まれます。パスワードは、"xyz" です。
a-Expense.ClaimsAware アプリケーションの Web.config ファイルで、 セクションを次の XML コードに置き換えます。Windows Azure プロジェクトを作成するときは、選択したサービス URL で **{service-url}**要素を置き換える必要があります。 Copy Code
<microsoft.identityModel>
<service>
<audienceUris>
<add value="https://{service-url}.cloudapp.net/" />
</audienceUris>
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true"
issuer="https://{adatum host}/{issuer endpoint}/"
realm="https://{service-url}.cloudapp.net/"
requireHttps="true" />
<cookieHandler requireSsl="true" />
</federatedAuthentication>
<issuerNameRegistry
type=
"Microsoft.IdentityModel.Tokens.
ConfigurationBasedIssuerNameRegistry,
Microsoft.IdentityModel, Version=3.5.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35">
<trustedIssuers>
<!--Adatum's identity provider -->
<add thumbprint=
"f260042d59e14817984c6183fbc6bfc71baf5462"
name="adatum" />
</trustedIssuers>
</issuerNameRegistry>
<certificateValidation
certificateValidationMode="None" />
</service>
</microsoft.identityModel>a-expense.cloud プロジェクトを右クリックし、[発行] をクリックします。これにより、ServiceConfiguration ファイルおよび Azure で実際に使用するためのパッケージが生成されます。
ServiceConfiguration ファイルとパッケージを Windows Azure プロジェクトに展開します。
a-Expense アプリケーションを Azure に展開したら、https://windows.azure.com (英語)にログオンしてテストできます。
注意
このアプリケーションを Azure (またはオンプレミス Web ファーム) で複数のロール インスタンスによって実行する場合は、各マシンに個別のキーが設定されているので、DPAPI を使用する既定の Cookie 暗号化メカニズムは適していません。
この場合は、既定の SessionSecurityHandlerオブジェクトを RsaEncryptionCookieTransformまたはカスタムの Cookie 変換機能に置き換えて構成する必要があります。これについては、WIF SDK に含まれる "Web ファーム" のサンプルで詳しく説明されています。
関連情報
このガイドの「付録 A」では、FedUtil を使用するチュートリアル、Web.config ファイルを編集する方法、および証明書の格納場所を示します。
MSDN® には、『MSDN Magazine』の「クレーム ベースの WCF サービスを構築するためのより優れたアプローチ」(https://msdn.microsoft.com/ja-jp/magazine/dd278426.aspx) を含む多くの有用な記事があります。
Windows Azure の詳細については、https://www.microsoft.com/japan/windowsazure/の「Windows Azure Platform」を参照してください。