[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]] -[[戻る>ASP.NET Identity]] * 目次 [#y767ea78] #contents *概要 [#x51e7243] [[ASP.NET Identity]]は、 **プロトコル [#ebe65571] ***[[OAuth]] [#td332652] [[OAuth]]の[[クレームベース認証]]のEndpoint追加をサポートしており、~ これにより、Java、JavaScript、Perl、PHP、Python、Rubyなどの~ 「非 .NET 環境」と認証処理を連携させることもできる。 この処理は、[[ASP.NET SPA]]テンプレートの以下のEndpointに実装されている。 -ASP.NET SPA (JavaScript) の Web API 認証 (ASP.NET Identity) ? Tsmatz~ https://blogs.msdn.microsoft.com/tsmatsuz/2014/05/20/asp-net-spa-javascript-web-api-asp-net-identity-html5biz/ --http://localhost:XXXX/Token Endpoint --http://localhost:XXXX/Account/Authorize Endpoint --http://localhost:XXXX/任意Resource用のEndpoint URLは変更可能。上記は既定値。 ***[[OpenId Connect]] [#o9809537] [[OpenId Connect]]のサーバー実装は、現時点(2016年)では提供されていない。 -https://github.com/jchannon/katanaproject/tree/master/src/Microsoft.Owin.Security.OpenIdConnect -https://github.com/jchannon/katanaproject/tree/master/src/Microsoft.Owin.Security.OAuth **認証サイト [#l4133d0e] ***構成 [#o5e298b4] -[[ASP.NET MVC]]アプリケーションとして作成する。 -[[ASP.NET Identity]]を用いて、各 Web アプリのアカウント管理を行う。 -ユーザー情報へのアクセスには、既定の[[Entity Framework]]を使用する。 -ユーザー情報は、既定の LocalDb に格納する。 ***準備 [#jcb91f7a] +Visual Studio 2015 で、新規 ASP.NET Web アプリケーションを作成する。 +「新しい ASP.NET プロジェクト」ダイアログで、以下を選択する。 --テンプレート: [[ASP.NET MVC]] --認証の変更: 個別のユーザー アカウント +Visual Studio の「パッケージ マネージャー コンソール」で、以下のコマンドを実行する。 Install-Package Microsoft.AspNet.WebApi Install-Package Microsoft.AspNet.WebApi.Owin Install-Package Microsoft.AspNet.WebApi.Cors **連携サイト(, システム, アプリ) [#o744ec42] ***[[cURLコマンド]] [#y3d89c8f] http://localhost:XXXX/Token Endpointのシナリオを検証する。 -HTTPClientなどから/Token Endpointにアクセスして連携するシナリオ。 -自サイト内に閉じないため、CORS (Cross-Origin Resource Sharing)への対応が必要。 ***JavaScript [#jeb0e69c] http://localhost:XXXX/Account/Authorize Endpointのシナリオを検証する。 -SPA(Browser+WebAPI)で、WebAPI(OAuthリソース)へのアクセスを認可するシナリオ。 -自サイト内に閉じるため、CORS (Cross-Origin Resource Sharing)への対応が不要。 * /Token Endpointの検証手順 [#a452ab9e] 以下のブログの内容を参考に、~ 「[[Resource Owner Password Credentialsグラント種別>#i2483bc0]]」のシナリオの検証を行うことができる。 -ASP.NET WebAPI2でAjaxでOAuth認証するよ~ (ついでにTypeScriptとReact) - かずきのBlog@hatena~ http://blog.okazuki.jp/entry/2016/01/15/215901 -asp.net - How do you consume extra parameters~ in OAuth2 Token request within .net WebApi2 application - Stack Overflow~ http://stackoverflow.com/questions/21243996/how-do-you-consume-extra-parameters-in-oauth2-token-request-within-net-webapi2 -c# - Can't get UserManager from OwinContext in apicontroller - Stack Overflow~ http://stackoverflow.com/questions/24001245/cant-get-usermanager-from-owincontext-in-apicontroller -Simple OAuth Server: Implementing a Simple OAuth Server~ with Katana OAuth Authorization Server Components (Part 1) - Tugberk Ugurlu's Blog~ http://www.tugberkugurlu.com/archive/simple-oauth-server-implementing-a-simple-oauth-server-with-katana-oauth-authorization-server-components-part-1 **前提 [#maa977e7] ここでは、以下のような前提の検証用アプリケーションを構築する。 +--------+ +----------------+ | 非 |--(A)- Authorization Request ->| ASP.NET | | . | | Identity | | N |<-(B)----- Bearer Token -------| | | E | | | | T |--(C)----- Bearer Token ------>| | +-----------+ | 環 | | |---| UserStore | | 境 |<-(D)--- Protected Resource ---| | +-----------+ +--------+ +----------------+ -処理順 > + (A) Authorization処理 と Bearer Token発行のEndpointへRequestする。 + (B) 認証処理後、内部ではClaimsIdentityを生成してSign-inされ、Bearer TokenがResponseされる。 + (C) Bearer Tokenを持って、Resources用のEndpointにRequestする。 + (D) Resources用のEndpointからClaim等のリソースがResponseされる。 -ポイント --Authorization処理 と Bearer Token発行のEndpoint~ http://localhost:XXXX/Token --Resources用のEndpoint~ http://localhost:XXXX/api/OAuthResource/GetClaim --連携サイト(, システム, アプリ)では、上記のResources用のEndpointから~ 取得したクレーム情報を元に、認可を行い、Cookie認証チェットを発行する。 **認証サイト開発 [#q8945633] コードの提示はGithub登録まで待ってください。 **Web アプリ開発 [#ke366e99] ここの検証では、[[cURLコマンド]]を使用するため開発不要。 **認証連携の動作検証 [#i6134f32] [[cURLコマンド]]を使用して認証連携の動作を検証する。 ***処理の概要 [#bf483c68] -/Token Endpointに対して以下のRequestを出すと、Bearer Tokenが返ってくる。 --POST --Content-Type: application/x-www-form-urlencoded; --body:grant_type=password&username=ユーザ名&password=パスワード -Bearer Tokenをヘッダに指定してResources用のEndpointにアクセスするとResources情報を取得できる。 --GET --Authorization: Bearer XXXXXXXXXX --Content-Type: application/json; charset=utf-8; ***[[cURLコマンド]] [#yf1216ba] Debug ProxyにFiddler等を使用すると尚良~ (其の際は、 --proxy オプションを指定する必要がある)。 -Bearer Tokenの取得 --Request (cURLコマンド) >curl "http://localhost/Token" -H "Content-Type: application/x-www-form-urlencoded;" -d "grant_type=password" -d "username=XXXXX" -d "password=YYYYY" --Response (Body) {"access_token":"XXXXXXXXXX","token_type":"bearer","expires_in":nnnnn} -Bearer Tokenを使用したOAuthリソースへのアクセス --Request (cURLコマンド) >curl "http://localhost/api/OAuthResource/GetClaim" -H "Authorization: Bearer XXXXXXXXXX" -H "Content-Type: application/json; charset=utf-8;" --Response (Body) {"id":"XXXXX","userName":"XXXXX","email":"XXXXX","phoneNumber":"XXXXX"} * /Account/Authorize/ Endpointの検証手順 [#p5f5a8e3] ここでは、以下の手順で作成した検証手順を使用して、~ 「[[Implicitグラント種別>#h347a7c6]]」のシナリオの検証を行うことができる。 +[[ASP.NET SPA]]テンプレートの動作確認を行なった後、 +[[ASP.NET MVC]]テンプレートの差分を確認した上で、 +[[OAuth]]に必要な実装を抽出し、 +[[ASP.NET MVC]]テンプレートに[[OAuth]]のEndpointを追加する手順を書き出し、 +その手順の妥当性を以下の検証手順によって検証した。 **前提 [#cac6a33f] ここでは、以下のような前提の検証用アプリケーションを構築する。 +--------+ +----------------+ | |--(A)- Authorization Request ->| | | | | | | |<-(B)-- Authorization Grant ---| | | | | | | 非 | | | | . | | | | N |--(C)-- Authorization Grant -->| ASP.NET | | E | | Identity | | T |<-(D)----- Bearer Token -------| Token認証機能 | | 環 | | | | 境 | | | | | | | | |--(E)----- Bearer Token ------>| | | | | | +-----------+ | |<-(F)--- Protected Resource ---| |---| UserStore | +--------+ +----------------+ +-----------+ -処理順 > + (A) 認証サイトのForms認証機構へRequestする。 + (B) 発行されたCookie認証チェットのResponseされる。 + (C) Cookie認証チェットを持って、[[OAuth]]用のEndpointにRequestする。~ 既に認証されているので、内部ではClaimsIdentityを生成してSign-inされる。~ すると、OAuthProviderがBearer Token用のEndpointにRedirectされる。 + (D) Bearer Token用のEndpointからBearer TokenがResponseされる。 + (E) Bearer Tokenを持って、Resources用のEndpointにRequestする。 + (F) Resources用のEndpointからClaim等のリソースがResponseされる。 -ポイント --[[OAuth]]用のEndpoint~ http://localhost:XXXX/Account/Authorize --Bearer Token用のEndpoint~ http://localhost:XXXX/Account/ReturnBearerTokenScreen --Resources用のEndpoint~ http://localhost:XXXX/api/OAuthResource/GetClaim **認証サイト開発 [#k9408908] コードの提示はGithub登録まで待ってください。 ***ApplicationOAuthProviderの追加 [#z15e0624] Providersフォルダを作成し、[[OAuth]]のProviderであるApplicationOAuthProviderを追加する。 ***Startup.Authで、定義したApplicationOAuthProviderを登録 [#n71f912c] 前述のApplicationOAuthProviderを[[OAuth]]のProviderとして登録する。 ***AccountControlleに、Authorizeメソッドを追加 [#q0c1012d] Authorizeメソッドで認証を行なう。 Authorizeメソッドで認証した後、 +Bearer Tokenを発行する。 +クライアントはBearer Tokenを使用してOAuthリソースにアクセスする。 +サーバはOAuthリソースへのアクセスを認可できるようになる。 ***AccountControlleにReturnBearerTokenScreenメソッドを追加 [#k381df07] Authorizeメソッド実行後にRedirectされる先のAction MethodとViewを準備する。 -Action Method~ URL に付与された、Bearer Token を取得し、Bearer Tokenを返す。 -View~ 通常、Bearer Tokenが露見しないように、Hiddnか何かに埋め込む。 ***WebApiConfigの追加 [#q040b99b] App_Startフォルダに、[[ASP.NET Web API]]の設定を行うためのWebApiConfig.csを追加する。 ***Global.Application_Startメソッドで、定義したWebApiConfigを登録 [#k795c063] Global.asax.csのApplication_Startメソッドで、定義したWebApiConfigの設定を登録。 ***OAuthClaimViewModelの追加 [#me6fe947] Models フォルダに、Claimを返すためのOAuthClaimViewModel.csを追加する。 ***OAuthResourceControllerの追加 [#j2264468] Controller フォルダに、Claimを返すためのOAuthResourceController.csを追加する。~ ここに、Claim等の[[OAuth]]のResourcesを返すための[[ASP.NET Web API]]のメソッドを追加する。 **Web アプリ開発 [#zda88633] JavaScriptとして実装する。 コードの提示はGithub登録まで待ってください。 **認証連携の動作検証 [#n7eec8a2] 次のURLでアクセスするだけでよい。 http://localhost/Account/Authorize?client_id=self&response_type=token /Account/Authorize/ Endpointに到達する前に、Forms認証されるため、~ /Account/Authorize/ Endpointでは、Forms認証のクレデンシャルを使用して認証し、~ Tokenを発行→OAuthリソースにアクセスする。 *その他 [#h1cb6120] **セキュリティに関する考察 [#v33a7e19] ***Resource Owner Password Credentialsグラント種別 [#jf8e8e73] HTTPSはホスト名の部分だけ情報として渡し、~ 以後のパスやクエリストリング情報は暗号化される。 従ってGETでも一応安全だが、 -アクセスログに残る -ブラウザの履歴に残る -リファラーに残る という問題がある。 従って、このグラント種別では、 -基本的に、Browserから実行させてはいけない。 -また、Webサーバで、W3Cログ等を出力させないようにする。 などが必要になると考える。 IISならW3Cログの出力をカスタマイズできる。 -参考 --HTTPSとQueryString ---security - Secure Oauth 2.0 Resource Owner Password Credentials Grant Type - Stack Overflow~ http://stackoverflow.com/questions/39129331/secure-oauth-2-0-resource-owner-password-credentials-grant-type ---httpsでqueryStringは安全か | Rutakeの技術メモ~ http://cloudfront.rutake.com/techmemo/2011/01/26/https%E3%81%A7querystring%E3%81%AF%E5%AE%89%E5%85%A8%E3%81%8B/ --QueryStringのログ出力 ---logging - Does IIS7 log request query string by default? - Stack Overflow~ http://stackoverflow.com/questions/19918561/does-iis7-log-request-query-string-by-default ---Does IIS log query strings in a https request? : The Official Microsoft IIS Forums~ https://forums.iis.net/t/1178176.aspx *参考 [#f733c473] **Tsmatz [#o09dc264] -ASP.NET SPA (JavaScript) の Web API 認証 (ASP.NET Identity) – Tsmatz~ https://blogs.msdn.microsoft.com/tsmatsuz/2014/05/20/asp-net-spa-javascript-web-api-asp-net-identity-html5biz/ **かずきのBlog@hatena [#ode84d2f] -ASP.NET WebAPI2でAjaxでOAuth認証するよ(ついでにTypeScriptとReact)~ http://blog.okazuki.jp/entry/2016/01/15/215901 -HttpClientクラスがリダイレクトをよきに計らってくれるのをどうにかしたい~ http://blog.okazuki.jp/entry/20121225/HttpClientTips **The OAuth 2.0 Authorization Framework [#v698197b] -RFC 6749 - The OAuth 2.0 Authorization Framework~ https://tools.ietf.org/html/rfc6749 ***RFC 6749 - 4.3. Resource Owner Password Credentials Grant [#a91d9d2e] -memo: Force.com : REST API 開発 ユーザ名パスワード OAuth 認証~ http://vaindespair.blogspot.jp/2013/01/blog-post_5252.html --Understanding the Username-Password OAuth Authentication Flow~ Force.com REST API Developer Guide | Salesforce Developers~ https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_username_password_oauth_flow.htm -Resource Owner Password Credentials Grantについては[[コチラ>#i2483bc0]]。 ***RFC 6750 - Bearer Token Usage [#d65223fc] -OAuth 2.0のbearer tokenの最新仕様を調べたらあまり変わってなかった - r-weblife~ http://d.hatena.ne.jp/ritou/20110402/1301679908 --The OAuth 2.0 Authorization Framework: Bearer Token Usage(日本語)~ http://openid-foundation-japan.github.io/rfc6750.ja.html -RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage~ https://tools.ietf.org/html/rfc6750 +--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+ ASP.NET Identityによる認証サイト~ = 上記図中のResource Owner, Authorization Server, Resource Serverに該当する。 **OAuth 2.0のフロー定義 [#kd90c6bf] OAuth 2.0仕様には4つのフローが定義されている。~ これらのフローのタイプを「グラント種別」と呼ばれる。 -IPA ISEC セキュア・プログラミング講座:~ Webアプリケーション編 第8章 マッシュアップ:サーバサイドマッシュアップ~ https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/709.html 以下の様な「グラント種別」がある模様。 ***Authorization Codeグラント種別 [#y8bf613e] -RFC 6749 - The OAuth 2.0 Authorization Framework~ 4.1. Authorization Code Grant~ https://tools.ietf.org/html/rfc6749#section-4.1 --Authorization Code Flow +----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI ---->| | | User- | | Authorization | | Agent -+----(B)-- User authenticates --->| Server | | | | | | -+----(C)-- Authorization Code ---<| | +-|----|---+ +---------------+ | | ^ v (A) (C) | | | | | | ^ v | | +---------+ | | | |>---(D)-- Authorization Code ---------' | | Client | & Redirection URI | | | | | |<---(E)----- Access Token -------------------' +---------+ (w/ Optional Refresh Token) Note: The lines illustrating steps (A), (B), and (C) are broken into two parts as they pass through the user-agent. ***Implicitグラント種別 [#h347a7c6] -RFC 6749 - The OAuth 2.0 Authorization Framework~ 4.2. Implicit Grant~ https://tools.ietf.org/html/rfc6749#section-4.2 --Implicit Grant Flow +----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI --->| | | User- | | Authorization | | Agent -|----(B)-- User authenticates -->| Server | | | | | | |<---(C)--- Redirection URI ----<| | | | with Access Token +---------------+ | | in Fragment | | +---------------+ | |----(D)--- Redirection URI ---->| Web-Hosted | | | without Fragment | Client | | | | Resource | | (F) |<---(E)------- Script ---------<| | | | +---------------+ +-|--------+ | | (A) (G) Access Token | | ^ v +---------+ | | | Client | | | +---------+ Note: The lines illustrating steps (A) and (B) are broken into two parts as they pass through the user-agent. ***Resource Owner Password Credentialsグラント種別 [#i2483bc0] -RFC 6749 - The OAuth 2.0 Authorization Framework~ 4.3. Resource Owner Password Credentials Grant~ https://tools.ietf.org/html/rfc6749#section-4.3 --Resource Owner Password Credentials Flow +----------+ | Resource | | Owner | | | +----------+ v | Resource Owner (A) Password Credentials | v +---------+ +---------------+ | |>--(B)---- Resource Owner ------->| | | | Password Credentials | Authorization | | Client | | Server | | |<--(C)---- Access Token ---------<| | | | (w/ Optional Refresh Token) | | +---------+ +---------------+ -補足 --ASP.NET Identityによる認証サイト = Authorization Server に該当する。 --Clientは、Authorization Serverの情報を元に認可をする連携サイト(, システム, アプリ)。 --Resource OwnerはUserIDやPasswordを保持しているユーザやシステム。 ***Client Credentialsグラント種別 [#ka6e3a8f] -RFC 6749 - The OAuth 2.0 Authorization Framework~ 4.3. Resource Owner Password Credentials Grant~ https://tools.ietf.org/html/rfc6749#section-4.4 --Client Credentials Grant +---------+ +---------------+ | | | | | |>--(A)- Client Authentication --->| Authorization | | Client | | Server | | |<--(B)---- Access Token ---------<| | | | | | +---------+ +---------------+ ---- Tags: [[:ASP.NET]], [[:ASP.NET MVC]], [[:ASP.NET SPA]], [[[[ASP.NET Web API]]]], [[:ASP.NET Identity]] Special thanks go to mg-san for his support.