Windows Azure AppFabric ACS使ってフェデレーション認証するのはいいけど、味気ないサインイン画面で辟易してる方も多いんじゃないでしょうか。
↓味気ないサインイン画面
というわけで今日はこいつのカスタマイズをしたいと思います。
ゴールとして今回はASP.NET MVC3のログイン画面内で上記のサインイン画面(というかセレクタ画面)を埋め込んでアプリケーションでちゃんと(?)制御できるようにしたいと思います。
とりあえず下地として 「Windows Azure AppFabric ACS Walkthrough」でも見て、ACSを使える環境にはしておいてください。
さてカスタムページですが、Azure AppFabric ACS管理ポータルにサンプルがあるのでまずはそちらを参考にしましょう。というかそのままパクる勢いでコピペしますんで。
管理ポータルから「アプリケーション統合」→「ログインページ」→「証明書利用者アプリケーション」の一覧から自分のアプリを選択し、「ログインページの統合」画面の「オプション2:ログインページをアプリケーションの一部としてホストする」の下にある「ログイン ページ例のダウンロード」ボタンをクリックして、サンプルを保存します。
ダウンロードしたサンプルを普通にブラウザで表示すると見慣れた画面が出ると思います。
このサンプル画面はすでに必要な情報埋め込まれてますので、そのままでもちゃんと動作します。AppFabric ACS側で設定したプロバイダ一覧をJSONで返す口が用意されてたりするので、見たまんまあまり困ることはないかと思います。
さてここからが本題。
Windows Identity Foundation SDKに付属してるウィザードを使用してSTSの追加などを行うとアプリケーション全体に対し認証が必要になってしまっています。
アプリケーションで制御したいのにこれはちょっと困りますね。ということでWeb.configの以下のlocation要素とauthorization要素を削除しましょう。
これで勝手にAzure AppFabric ACSの既定のログオン画面に飛ばされることはなくなりました。
次はログオン画面のカスタマイズです。
今回はASP.NET MVC3を使っているのでログオン画面のビューであるLogOn.chtmlの内容をさきほどダウンロードしたサンプルのHTMLにさくっと適当に入れ替えます。
IDがMainのDIV要素内全部と、JavaScriptが肝です。
IDきにくわねぇとかそういう人はJavaScript内のコード含めて適当に修正してください。あとJavaScript内で@を使ってるのでエスケープが必要ですね。(今回はRazor使ってるので)
最後の一行でAzure AppFabric ACSから設定したIdPの一覧などをJSON形式で取得しますが、Realmなどアプリケーション固有の情報を埋め込む必要があるので注意ください。(管理ポータル側で正しく設定した後でサンプルダウンロードしたら大丈夫だと思いますが)
変更点は以上です。これで最低限動作しますので実際に実行してみましょう。
こんな感じでログイン画面に行けばIdPの一覧が表示されて、それぞれのIdPを選択すればそれぞれのログイン画面にリダイレクトされ、認証した後指定したページに再度リダイレクトされます。
ログイン情報はWIFのウィザード使っていれば埋め込まれてますのでUser.Identityなどでアクセスすることができます。
※より細かいクレーム情報などは ((IClaimsIdentity)User.Identity).Claims.Where(c => c.ClaimType == ClaimTypes.Email).SingleOrDefault().Value とかするとEmailが取れます。(ただしクレームに含まれている場合)
さてこれでログインはOKですがそのままだとログオフできません。
ASP.NET MVC3の標準のテンプレートだと FormsAuthentication.SignOut() しか読んでいませんが、これだとWIF使ってると綺麗にクリアされません。
ということで該当行を
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.FederatedSignOut(new Uri("http://127.0.0.1:81/"),null);
のように書き換えます。※URIはログオフ後の遷移先
※Microsoft.IdentityModelアセンブリを追加することを忘れずに
ちなみに FederatedSignOut メソッドを呼んだらリダイレクトされるので、その後のRedirectToActionメソッドで記述してるリダイレクトは無視されると思います。
というわけで、こんな感じで一通りカスタマイズができるようになりました。
あくまでPassive Federationなので注意が必要ですが、だいぶアプリケーションに統一感がだせるようになったかと思います。
これでログイン画面のデザインも自由にできますね!(白目