前回の投稿では OWIN でマルチホストしましたが、今回はミドルウェアの Windows Azure Active Directory(WAAD)認証ライブラリを利用して、ASP.NET Web API を OAuth 2.0 認証してみます。元ネタはこちらですが、Visual Studio のテンプレート機能を使わずに、手動で構築します。
また、ネイティブ クライアント アプリからの認証では、Active Directory Authentication Library(ADAL)がいい感じなので、使ってみました。ADAL は、WAAD 向けの認証ライブラリで、以前は Windows Azure Authentication Library として提供されていたライブラリが名称変更されています。
Web API アプリを作成
Web アプリのテンプレートから Empty を選択し、Web API のみチェックして WebApiApp プロジェクトを新規作成します。GETで"api/test"にリクエストすると、ユーザー名を返すシンプルな Web API を追加し、忘れずに Authorize 属性を付けます。デバッグ実行し、レスポンスに 401 が返ることを確認しつつ、localhost のポート番号をメモしておきます。
#TestController.cs [Authorize] public class TestController : ApiController { public string Get() { return base.User.Identity.Name; } }
Web API アプリを WAAD に登録
ポータルから WAAD に、Web API アプリを追加します。ここでは、WAAD のドメイン名を「example.onmicrosoft.com」とします。新規に WAAD を作成する場合、一度作成すると削除できないようなので、ご注意ください。ウィザード画面で必要な情報を入力します。
ここでは、以下のように設定しました。
- NAME:WebApiApp
- SIGN-ON URL:http://localhost:61249/
- APP ID URI:https://example.onmicrosoft.com/WebApiApp
- Directory access:SINGLE SIGN-ON
Web API アプリに WAAD 認証を追加
WebApiApp プロジェクトに NuGet パッケージをインストールします。
- Install-package Microsoft.Owin.Host.SystemWeb
- Install-package Microsoft.Owin.Security.ActiveDirectory
OWIN パイプラインに WAAD 認証のライブラリを追加します。Audience には、ポータルに登録した WebApiApp の APP ID URI を設定します。
#Startup.cs [assembly: OwinStartup(typeof(WebApiApp.Startup))] namespace WebApiApp { public class Startup { public void Configuration(IAppBuilder app) { app.UseWindowsAzureActiveDirectoryBearerAuthentication( new WindowsAzureActiveDirectoryBearerAuthenticationOptions { Audience = "https://example.onmicrosoft.com/WebApiApp", Tenant = "example.onmicrosoft.com" }); } } }
ネイティブ クライアント アプリを WAAD に登録
ポータルから WAAD に、ネイティブ クライアント アプリを追加します。ウィザード画面で必要な情報を入力します。
ここでは、以下のように設定しました。
- NAME:WpfApp
- REDIRECT URI:https://example.onmicrosoft.com/WpfApp
WpfApp を登録後、さきほど登録した WebApiApp との関連付けを行っておきます。
ネイティブ クライアント アプリを作成
WPFアプリとして、WpfApp プロジェクトを新規作成します。ネイティブ クライアント アプリの認証では、Webブラウザコントロールを利用した面倒な実装が必要となるのですが、Active Directory Authentication Libraryを使うと、このあたりの実装をライブラリが行ってくれます。WpfApp プロジェクトに NuGet パッケージをインストールします。
- Install-package Microsoft.IdentityModel.Clients.ActiveDirectory
- Install-Package Microsoft.AspNet.WebApi.Client
ボタンクリックイベントで WAAD 認証して、WebAPI を呼び出すシンプルなアプリです。9行目のコードで ADAL が認証してくれますので、取得した Bearer トークンをHTTPヘッダーに設定すれば OK です。WpfApp の Client ID は、ポータルから取得できます。
#MainWindow.xaml.cs private async void Button_Click(object sender, RoutedEventArgs e) { var authority = "https://login.windows.net/example.onmicrosoft.com"; var appId = "https://example.onmicrosoft.com/WebApiApp"; // WebApiApp の APP ID URI var clientId = "c3d3af4a-1682-4e49-abd8-4a8e580cebf1"; // WpfApp の Client ID var redirectUri = new Uri("https://example.onmicrosoft.com/WpfApp"); // WpfApp の REDIRECT URI // Windows Azure Active Directory 認証 var authRes = new AuthenticationContext(authority).AcquireToken(appId, clientId, redirectUri); // 取得したトークンで、Web API を呼び出し var client = new HttpClient(); client.DefaultRequestHeaders.Add(HttpRequestHeader.Authorization.ToString(), authRes.CreateAuthorizationHeader()); var result = await client.GetStringAsync("http://localhost:61249/api/test"); this.textBlock1.Text = result; }
実行結果
まず、ネイティブ クライアント アプリからサインインするユーザーを、ポータルから登録しておきます。ここでは、WAAD のユーザー名を「tony@example.onmicrosoft.com」とします。
WpfApp のボタンをクリックすると、サインイン画面が表示され、認証に成功すると WebAPI から結果を取得できます。
まとめ
クラウドで Web API を公開するなら、セキュリティは避けては通れない道です。OWIN のミドルウェアで提供されるフレームワークやライブラリを自由に組み合わせて、Web アプリを構築できる時代が始まっているのだと実感しました。