トークンベースの認証機能の実装(ASP.NET Web API + Owin + ASP.NET Identity 2) | ||
|
先日、とあるWebアプリ(Azure Webサイト)に認証機能を実装する際に、ASP.NET Identity 2.0 をに基づいた「トークンベースの認証」を組み込んだので、その実装の流れについて整理しておきたいと思います。
今回のトークンベース認証(OAuthベアラトークン)の実装にあたっては、RESTfulな Webサービス環境において ASP.NET Web API を使い、認証機能については、拡張性の高い ASP.NET Identity 2.0 を使うことにしました。
適用したテクノロジーは次の通りです。
・ASP.NET Web API
RESTベース(JSONフォーマット)Webサービスとして認証機能を実装。
・CORS(Cross-Origin Resource Sharing)
オリジン(HTMLを読み込んだサーバのこと)以外のサーバからデータを取得する仕組み。
・Owin(Open Web Interface for .NET)
サーバーとアプリを抽象化するインタフェース( .NETのWebサーバー/アプリ向けの、オープンな標準インターフェースのミドルウェア)。
認証やCORSなどの機能を抽象化します。(IISに依存しない環境での動作を実現します。)
・ASP.NET Identity 2
従来の Membership provider とは違い、SQL Server以外のデータストアの利用、ユニットテストが容易になり、FacebookやTwitterを使った認証にも標準で対応しています。
なお、ASP.NET Identityは、OWINとの連携を前提に作られています。
提供機能としては、パスワードのリセットやアカウントのロックアウトなどの機能がフレームワークレベルで提供されており、二要素認証およびソーシャルログインに対応しています。
(メール送信機能もあります。(もちろんメールサーバー(SoftGrid(Azureにもあります)など)の準備は必要ですが...))
・OAuth(Open Authorization 認証)
Web上の情報委譲形式「 OAuth」を利用して、異なるサービス間での認可情報を受け渡しを行う認証機構。
(今回は、Bearerトークンによる認証を使います。)
それでは、次に今回の「OAuthのベアラトークンに基づく認証機能」の実装のながれについて整理していきます。
【ASP.NET Web API 上に必要環境を準備】
まずは、ベースとなる Web API プロジェクトを作成し、NuGetを使用して必要なパッケージをインストールします。
空のソリューションを作成し、ASP.NET Web API のプロジェクトを追加します。 「ASP.NET Web アプリケーション」を選択します。 テンプレートの選択から、「Empty」で「Web API」を選択します。
認証は、「認証なし」にしておきます。 作成した該当プロジェクトにおいて、「NuGetパッケージ管理」を呼び出します。 今回必要となるパッケージを検索し、インストールします。
まずは、OWINのパッケージ(Microsoft.AspNet.WebApi.Owin)をインストールします。 「同意します」。 関連するパッケージがインストールされます。 続いて、IISベースのAzure Webサイトなどで、ASP.NETのリクエストを OWINサーバー間でやり取り可能にするためのパイプライン機能として Microsoft.Owin.Host.SystemWeb をインストールします。
【OWINのスタートアップクラスを用意】
続いて、サーバーの初期起動時に一度動作するスタートアップクラスを作成します。 このクラスは、Startup クラスで、IAppBuilderパラメータを通じて Owinサーバーと認証機能を連携させます。 上のConfigurationメソッド中において、WebApiConfigクラスのRegisterにHttpConfigurationオブジェクトを渡します。 Startupクラスの実装により、従来の Global.asax 上の Application_Start での初期動作は不要になったので、Global.asax 自体を削除しておきます。
【ASP.NET Identity を組み込みます】
認証機能を実装するために、NuGetを使い ASP.NET Identity 2 に関連するパッケージを検索・インストールします。
まずは、Microsoft.AspNet.Identity.Owin をインストールします。 次に、ASP.NET Identity で SQL Server データベースを使えるように、Microsoft.AspNet.Identity.EntityFramework をインストールします。
【ASP.NET Identity のためのクラスを用意】
続いて、ASP.NET Identity のための DBコンテキストクラスを用意します。
ここでの定義により、.NET Entity Framework のコード・ファーストの機能により、所定の SQLデータベース上に該当のエンティティが自動作成されます。 IdentityUser を継承したクラス(ここでは、AuthUser)で、追加のエンティティフィールドを定義します。
IdentityDbContext を継承したクラス(ここでは、AuthDbContext)で、DBコンテキストを定義します。(追加のエンティティは、ここで DbSet として定義します。(併せて、コード・ファーストでエンティティが自動生成されます。))
なお、この二つのクラスは、ここでは同じファイル上に実装していますが、別々に実装する方が分かり易いと思います。 併せて、Web.Config で、接続先のデータベースを指定します。(ConnectionString)
先の AuthDbContext の base で指定した名前と、ここでの ConnectionString の名前が紐付きます。 続いて、ASP.NET Identity において、UserManager を継承したユーザー管理を司るクラス(ここでは、AuthUserManager)を作成します。 それから、認証時などでユーザー情報をいろいろとやり取りするためのペイロードクラス(ここでは、UserModel)も作成しておきます。
【ASP.NET Identity をサポートするためのリポジトリクラスを用意】
続いて、ASP.NET Identity において認証機能を実現するため2つの機能(RegisterUser(ユーザー登録)とFindUser(ユーザー確認))を実装するリポジトリクラスを作成します。 それぞれのメソッドを、次のように定義します。
いずれも、先の UserManager に委ねます。
【ASP.NET Web API のコントローラを作成】
次に、ASP.NET Web API として外部からアカウントを操作するためのコントローラを作成します。 空のコントローラを選択します。 次のように、登録用のメソッドを定義します。
先に用意したリポジトリクラスの RegisterUser を使います。 ここまで実装したら、ビルドし、デバッグ起動した上で、POASMAN(Google Chromeアプリとして提供される)を使って該当の Web API を使ってアカウント情報を登録してみます。
Postmanを Google Chrome のアプリの中から起動して、次のように /api/account/register に対して、JSON形式で POST します。 うまく実行されると、Entity Framework のコード・ファーストにより、所定のデータベース上に必要テーブルが制裁され、アカウント管理用のテーブル(AspNetUsers)に該当データが格納されます。(パスワードはハッシュされています。) とりあえずここまてで、ASP.NET Identity の基本的な実装は完了しました。
続いて、認証機能の実装に入ります。
【ASP.NET Web API に認証テスト用のコントローラを作成】
その前に、認証テスト用として、認証が必要な Web API のコントローラを一つ追加しておきます。
認証が必要なように、[Authorize]属性を付けておきます。 試しに、Postman を使い、認証なしで該当メソッドを読んでみます。
拒否されることが確認できます。
【OAuth に基づくベアラトークンでの認証機能の実装】
続いて、OAuth に基づいた認証機能(ベアラトークンに基づく)を実装します。
まずは、NuGetから OAuth のために必要なパッケージ(Microsoft.Owin.Security.OAuth)をインストールします。 先に定義した Startup クラスに、ベアラ認証のためのコードを追加します。
トークンは、http://xxxxx/token で取得できるようになります。
また、ここでの設定では、トークンの有効期限は 24時間に設定しています。(AccessTokenExpireTimeSpan = TimeSpan.FromDays(1))
また、認証は、SimpleAuthorizationServerProvider というカスタムクラス(後述)で処理するように定義しています。
【認証処理のためのクラスの実装】
先に、使うと宣言した認証処理のためのカスタムクラス(SimpleAuthorizationServerProvider)を追加・作成します。
まずはフォルダ(Providers)を作成します。 そこに、OAuthAuthorizationServerProvider を継承した認証処理のためのカスタムクラス(SimpleAuthorizationServerProvider)を作成します。
ValidateClientAuthentication と GrantResourceOwnerCredentials をオーバーライドしたメソッドを定義します。
GrantResourceOwnerCredentials では、リポジトリメソッドの FindUser をコールして、ユーザー&パスワードを認証します。
認証が成功したら、ClaimsIdentity クラスから bearerトークンと“sub”,”role”のクレーム情報を生成・保持します。 後は、この情報を使って、認証が必要な Web API にアクセスすれば OK です。
【CORSの実装】
次に、ASP.NET Web API が他のサイトとの間でデータのやり取りができるように、CORS(Cross-Origin Resource Sharing)の実装を行います。
まずは、NuGetを使い、次の必要なパッケージをインストールします。
Microsoft.Owin.Cors
Microsoft.AspNet.WebApi.Cors 続いて、先に定義した Startup クラスに、CORSを許可する定義を追加します。
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
【ベアラトークンの取得テスト】
全ての実装が終わったので、最後に、Postmanを使い、認証テスト(bearerトークンの取得テスト)をしてみます。
次のように、.../token に対して、Content-Type に application/x-www-form-urlencoded をセットし、grant_type に password、username に ユーザーID、password に パスワードを設定し、POST します。
成功したら、アクセストークンが返ってきます。 このトークンを使用して、先程、拒否されたテスト用の Web API メソッドをアクセスすると、うまくいきます。
Authorization ヘッダーに、”Bearer トークン文字列”を設定して GET を実行します。
以上で、ASP.NET Web API 上で、ASP.NET Identity を使い、OAuthに基づくベアラ認証の実装は完了です。
あとは、認証の際に取得したアクセストークンを使って、認証が必要な Web API にアクセスすることで実装したいろいろな Web API を利用することができます。
RESTful(JSON形式)なので、Ajax経由でクライアントサイドからの 認証によりセキュアなASP.NET Web API 利用が可能になります。
今回のトークンベース認証(OAuthベアラトークン)の実装にあたっては、RESTfulな Webサービス環境において ASP.NET Web API を使い、認証機能については、拡張性の高い ASP.NET Identity 2.0 を使うことにしました。
適用したテクノロジーは次の通りです。
・ASP.NET Web API
RESTベース(JSONフォーマット)Webサービスとして認証機能を実装。
・CORS(Cross-Origin Resource Sharing)
オリジン(HTMLを読み込んだサーバのこと)以外のサーバからデータを取得する仕組み。
・Owin(Open Web Interface for .NET)
サーバーとアプリを抽象化するインタフェース( .NETのWebサーバー/アプリ向けの、オープンな標準インターフェースのミドルウェア)。
認証やCORSなどの機能を抽象化します。(IISに依存しない環境での動作を実現します。)
・ASP.NET Identity 2
従来の Membership provider とは違い、SQL Server以外のデータストアの利用、ユニットテストが容易になり、FacebookやTwitterを使った認証にも標準で対応しています。
なお、ASP.NET Identityは、OWINとの連携を前提に作られています。
提供機能としては、パスワードのリセットやアカウントのロックアウトなどの機能がフレームワークレベルで提供されており、二要素認証およびソーシャルログインに対応しています。
(メール送信機能もあります。(もちろんメールサーバー(SoftGrid(Azureにもあります)など)の準備は必要ですが...))
・OAuth(Open Authorization 認証)
Web上の情報委譲形式「
(今回は、Bearerトークンによる認証を使います。)
それでは、次に今回の「OAuthのベアラトークンに基づく認証機能」の実装のながれについて整理していきます。
【ASP.NET Web API 上に必要環境を準備】
まずは、ベースとなる Web API プロジェクトを作成し、NuGetを使用して必要なパッケージをインストールします。
空のソリューションを作成し、ASP.NET Web API のプロジェクトを追加します。 「ASP.NET Web アプリケーション」を選択します。 テンプレートの選択から、「Empty」で「Web API」を選択します。
認証は、「認証なし」にしておきます。 作成した該当プロジェクトにおいて、「NuGetパッケージ管理」を呼び出します。 今回必要となるパッケージを検索し、インストールします。
まずは、OWINのパッケージ(Microsoft.AspNet.WebApi.Owin)をインストールします。 「同意します」。 関連するパッケージがインストールされます。 続いて、IISベースのAzure Webサイトなどで、ASP.NETのリクエストを OWINサーバー間でやり取り可能にするためのパイプライン機能として Microsoft.Owin.Host.SystemWeb をインストールします。
【OWINのスタートアップクラスを用意】
続いて、サーバーの初期起動時に一度動作するスタートアップクラスを作成します。 このクラスは、Startup クラスで、IAppBuilderパラメータを通じて Owinサーバーと認証機能を連携させます。 上のConfigurationメソッド中において、WebApiConfigクラスのRegisterにHttpConfigurationオブジェクトを渡します。 Startupクラスの実装により、従来の Global.asax 上の Application_Start での初期動作は不要になったので、Global.asax 自体を削除しておきます。
【ASP.NET Identity を組み込みます】
認証機能を実装するために、NuGetを使い ASP.NET Identity 2 に関連するパッケージを検索・インストールします。
まずは、Microsoft.AspNet.Identity.Owin をインストールします。 次に、ASP.NET Identity で SQL Server データベースを使えるように、Microsoft.AspNet.Identity.EntityFramework をインストールします。
【ASP.NET Identity のためのクラスを用意】
続いて、ASP.NET Identity のための DBコンテキストクラスを用意します。
ここでの定義により、.NET Entity Framework のコード・ファーストの機能により、所定の SQLデータベース上に該当のエンティティが自動作成されます。 IdentityUser を継承したクラス(ここでは、AuthUser)で、追加のエンティティフィールドを定義します。
IdentityDbContext を継承したクラス(ここでは、AuthDbContext)で、DBコンテキストを定義します。(追加のエンティティは、ここで DbSet として定義します。(併せて、コード・ファーストでエンティティが自動生成されます。))
なお、この二つのクラスは、ここでは同じファイル上に実装していますが、別々に実装する方が分かり易いと思います。 併せて、Web.Config で、接続先のデータベースを指定します。(ConnectionString)
先の AuthDbContext の base で指定した名前と、ここでの ConnectionString の名前が紐付きます。 続いて、ASP.NET Identity において、UserManager を継承したユーザー管理を司るクラス(ここでは、AuthUserManager)を作成します。 それから、認証時などでユーザー情報をいろいろとやり取りするためのペイロードクラス(ここでは、UserModel)も作成しておきます。
【ASP.NET Identity をサポートするためのリポジトリクラスを用意】
続いて、ASP.NET Identity において認証機能を実現するため2つの機能(RegisterUser(ユーザー登録)とFindUser(ユーザー確認))を実装するリポジトリクラスを作成します。 それぞれのメソッドを、次のように定義します。
いずれも、先の UserManager に委ねます。
【ASP.NET Web API のコントローラを作成】
次に、ASP.NET Web API として外部からアカウントを操作するためのコントローラを作成します。 空のコントローラを選択します。 次のように、登録用のメソッドを定義します。
先に用意したリポジトリクラスの RegisterUser を使います。 ここまで実装したら、ビルドし、デバッグ起動した上で、POASMAN(Google Chromeアプリとして提供される)を使って該当の Web API を使ってアカウント情報を登録してみます。
Postmanを Google Chrome のアプリの中から起動して、次のように /api/account/register に対して、JSON形式で POST します。 うまく実行されると、Entity Framework のコード・ファーストにより、所定のデータベース上に必要テーブルが制裁され、アカウント管理用のテーブル(AspNetUsers)に該当データが格納されます。(パスワードはハッシュされています。) とりあえずここまてで、ASP.NET Identity の基本的な実装は完了しました。
続いて、認証機能の実装に入ります。
【ASP.NET Web API に認証テスト用のコントローラを作成】
その前に、認証テスト用として、認証が必要な Web API のコントローラを一つ追加しておきます。
認証が必要なように、[Authorize]属性を付けておきます。 試しに、Postman を使い、認証なしで該当メソッドを読んでみます。
拒否されることが確認できます。
【OAuth に基づくベアラトークンでの認証機能の実装】
続いて、OAuth に基づいた認証機能(ベアラトークンに基づく)を実装します。
まずは、NuGetから OAuth のために必要なパッケージ(Microsoft.Owin.Security.OAuth)をインストールします。 先に定義した Startup クラスに、ベアラ認証のためのコードを追加します。
トークンは、http://xxxxx/token で取得できるようになります。
また、ここでの設定では、トークンの有効期限は 24時間に設定しています。(AccessTokenExpireTimeSpan = TimeSpan.FromDays(1))
また、認証は、SimpleAuthorizationServerProvider というカスタムクラス(後述)で処理するように定義しています。
【認証処理のためのクラスの実装】
先に、使うと宣言した認証処理のためのカスタムクラス(SimpleAuthorizationServerProvider)を追加・作成します。
まずはフォルダ(Providers)を作成します。 そこに、OAuthAuthorizationServerProvider を継承した認証処理のためのカスタムクラス(SimpleAuthorizationServerProvider)を作成します。
ValidateClientAuthentication と GrantResourceOwnerCredentials をオーバーライドしたメソッドを定義します。
GrantResourceOwnerCredentials では、リポジトリメソッドの FindUser をコールして、ユーザー&パスワードを認証します。
認証が成功したら、ClaimsIdentity クラスから bearerトークンと“sub”,”role”のクレーム情報を生成・保持します。 後は、この情報を使って、認証が必要な Web API にアクセスすれば OK です。
【CORSの実装】
次に、ASP.NET Web API が他のサイトとの間でデータのやり取りができるように、CORS(Cross-Origin Resource Sharing)の実装を行います。
まずは、NuGetを使い、次の必要なパッケージをインストールします。
Microsoft.Owin.Cors
Microsoft.AspNet.WebApi.Cors 続いて、先に定義した Startup クラスに、CORSを許可する定義を追加します。
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
【ベアラトークンの取得テスト】
全ての実装が終わったので、最後に、Postmanを使い、認証テスト(bearerトークンの取得テスト)をしてみます。
次のように、.../token に対して、Content-Type に application/x-www-form-urlencoded をセットし、grant_type に password、username に ユーザーID、password に パスワードを設定し、POST します。
成功したら、アクセストークンが返ってきます。 このトークンを使用して、先程、拒否されたテスト用の Web API メソッドをアクセスすると、うまくいきます。
Authorization ヘッダーに、”Bearer トークン文字列”を設定して GET を実行します。
以上で、ASP.NET Web API 上で、ASP.NET Identity を使い、OAuthに基づくベアラ認証の実装は完了です。
あとは、認証の際に取得したアクセストークンを使って、認証が必要な Web API にアクセスすることで実装したいろいろな Web API を利用することができます。
RESTful(JSON形式)なので、Ajax経由でクライアントサイドからの 認証によりセキュアなASP.NET Web API 利用が可能になります。
- 2015-02-10 :
- ASP.NET Identity :
- コメント : 1 :
- トラックバック 0