[[Open棟梁>https://github.com/OpenTouryoProject]] wiki

-[[戻る>Multi-AuthSystem]]

*目次 [#w492a716]
#contents

*概要 [#p3c82f83]
Multi-AuthSystem独自仕様部分について説明する。

*Idp仕様 [#c803a92a]
Idpの使用について。

**UserStore [#gd06e168]
**概要 [#lab61c15]
概ね、ASP.NET Identityに準拠。

ASP.NET Identity側の仕様については、「[[ASP.NET Identity>https://techinfoofmicrosofttech.osscons.jp/index.php?ASP.NET%20Identity]]」を参照。

**カスタマイズポイント [#z2504cd5]
***ユーザアカウント [#p70b0543]
-UserId = e-mail address = UserNameとする。
-Passwordの強度は[[下記の設定>#pe833de6]]に従う。

***UserStore [#gd06e168]
-EntityFrameworkをキャンセルしUserStoreクラスで実装。
-DBMSはSQL Server or PostgreSQLを使用。
-Open棟梁のB・D層を使用してデータアクセスを実装。

**パラメタ [#pe833de6]
**パラメタ化 [#pe833de6]
ASP.NET Identityや、その他、アプリケーションで使用するパラメタについて。

*外部認証仕様 [#q865b16d]
外部認証の使用について。
***SecurityStamp [#h652b8fd]
 <!-- SecurityStamp(検証間隔は10秒、本番は長めに設定-->
 <add key="SecurityStampValidateIntervalFromSeconds" value="10" />

-外部認証で取得したe-mail addressは検証しない。
***ユーザ名と、その検証 [#x5d3a6ba]
 <!--ユーザ名検証(ユーザ名は、E-mail-->
 <add key="AllowOnlyAlphanumericUserNames" value="false" />
 <add key="RequireUniqueEmail" value="true" />

***パスワード検証 [#mb726395]
 <!--パスワード検証(8文字以上の大文字・小文字、数値、記号-->
 <add key="RequiredLength" value="8" />
 <add key="RequireNonLetterOrDigit" value="true" />
 <add key="RequireDigit" value="true" />
 <add key="RequireLowercase" value="true" />
 <add key="RequireUppercase" value="true" />

***ユーザ ロックアウト [#se80b47a]
 <!--ユーザ ロックアウト(5 回入力ミスすると、5分ロックアウト-->
 <add key="UserLockoutEnabledByDefault" value="true" />
 <add key="DefaultAccountLockoutTimeSpanFromSeconds" value="300" />
 <add key="MaxFailedAccessAttemptsBeforeLockout" value="5" />

***二要素認証 [#r58fd201]
 <!-- 二要素認証(2FA:TwoFactorAuthentication)-->
 <!-- 必要に応じてユーザが有効にするので初期値は false -->
 <add key="TwoFactorEnabled" value="false" /> 
 <!-- Cookieの有効期限は二週間 24 * 14 = 336 時間 -->
 <add key="TwoFactorCookieExpiresFromHours" value="336" />

*外部認証仕様(≒ OAuth 2.0 Client仕様) [#q865b16d]
「≒」としたのは、外部認証の主要プロトコルがOAuth 2.0であって、~
今後、[[OpenID Connect>https://techinfoofmicrosofttech.osscons.jp/index.php?OpenID%20Connect]]などの他のプロトコルに置き換えられていく可能性があるため。

**概要 [#ac980dda]
概ね、ASP.NET Identityに準拠。

ASP.NET Identity側の仕様については、「[[ASP.NET Identityの外部ログイン>https://techinfoofmicrosofttech.osscons.jp/index.php?ASP.NET%20Identity%E3%81%AE%E5%A4%96%E9%83%A8%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3]]」を参照。

**カスタマイズ・ポイント [#u7a996a6]
外部認証処理の仕様について。

-外部認証処理で取得したe-mail addressは検証しない。
-e-mail addressでサインアップして、そのままサインインする。
-初回のサインアップを外部認証で行った場合、パスワードを持たないアカウントになる。~
この場合、後からパスワードを持ったアカウントとしての登録が不可能になる(★パスワードリセット不可能?)。

*OAuth2.0 Server仕様 [#q3ec8431]
**パラメタ化 [#r210fb5c]
以下のように各、外部ログイン・プロバイダの([[OAuth>https://techinfoofmicrosofttech.osscons.jp/index.php?OAuth]]等)の

ASP.NET Identityの仕様については、「[[ASP.NET Identity追加仕様>https://techinfoofmicrosofttech.osscons.jp/index.php?ASP.NET%20Identity%E3%81%AB%E3%82%88%E3%82%8BSTS%E5%AE%9F%E8%A3%85#z90cfe4c]]」を参照。
-有効化・無効化
-クライアント認証のためのクライアント識別子

を設定できる。

 <!-- 外部ログインの追加時に XSRF の防止 -->
 <add key="XsrfKey" value="(サイト毎にで変更する、公開しないこと)" />
  
 <!--外部ログイン(MicrosoftAccountAuthentication)-->
 <add key="MicrosoftAccountAuthentication" value="true" />
 <add key="MicrosoftAccountAuthenticationClientId" value="・・・" />
 <add key="MicrosoftAccountAuthenticationClientSecret" value="・・・" />
  
 <!--外部ログイン(GoogleAuthentication)-->
 <add key="GoogleAuthentication" value="true" />
 <add key="GoogleAuthenticationClientId" value="・・・" />
 <add key="GoogleAuthenticationClientSecret" value="・・・" />
  
 <!--外部ログイン(FacebookAuthentication)-->
 <add key="FacebookAuthentication" value="true" />
 <add key="FacebookAuthenticationClientId" value="・・・" />
 <add key="FacebookAuthenticationClientSecret" value="・・・" />

***設定値の取得方法など [#fe43fb5c]
クライアント識別子は、外部ログイン・サービスの管理画面から取得する。

合わせてここでRedirectエンドポイントの設定などを行う必要がある。~
これは、外部ログイン・サービス毎に設定方法が異なるので注意する。

例えばマイクロソフト・アカウントでは、以下の様な設定を行う。、
 https://fqdnname:nnnnn/signin-microsoft

外部ログイン・サービスによっては、~
httpやlocalhostをサポートしないことがある。

マイクロソフト・アカウントでは、部分一致をサポートしており、~
Redirectエンドポイントの以降のパスはredirect_uriから指定する。

外部ログインは、[[HttpUnauthorizedResult>https://msdn.microsoft.com/ja-jp/library/system.web.mvc.httpstatuscoderesult.aspx]]のActionResultを返すことで開始する。~
redirect_uriはHttpUnauthorizedResultのコンストラクタから指定できる。

***XsrfKey [#v08882f3]
-asp.net mvc 5 - What is the XsrfKey used for and should I set the XsrfId to something else? - Stack Overflow~
http://stackoverflow.com/questions/32121504/what-is-the-xsrfkey-used-for-and-should-i-set-the-xsrfid-to-something-else

XsrfKeyは、XSRF = CSRFを防ぐためのstateパラメタの生成に使用される。~
stateパラメタは暗号化によって生成されるので、XsrfKey自体が露見することはない。~
従って、この値としても、無作為な値を使用する必要はない。

*OAuth 2.0 Server仕様 [#q3ec8431]

**概要 [#s811486b]
概ね、ASP.NET Identityに準拠。

ASP.NET Identity側の仕様については、「[[ASP.NET IdentityによるSTS実装>https://techinfoofmicrosofttech.osscons.jp/index.php?ASP.NET%20Identity%E3%81%AE%E5%A4%96%E9%83%A8%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3]]」]]」を参照。

ASP.NET Identity側の仕様については、「[[ASP.NET Identity追加仕様>]]」を参照。

**共通 [#se391923]

***Server側 [#k813af7a]
-AuthorizationServer
--認可エンドポイント
---redirect_uriチェックは不要(部分一致をサポートしない完全事前登録制とするため)
--Tokenエンドポイント(Access Tokenの発行方法)
---scope=その他の値の場合、scopeパラメタ値をClaimに格納する(通常の動作)。

-ResourceServer
--リソース・アクセス用のWebAPIを提供する。
---"urn:oauth:scope"のClaimがあった場合、scopeの値に適合した範囲のアクセス権で処理を行う。

***Client側 [#jdcc345f]
-パラメタ
--redirect_uri指定は不要(部分一致をサポートしない完全事前登録制とするため)
--stateの使用を強く推奨する(Access Token露見は、Client側の自己責任のため)。

-ResourceServerリソース・アクセス用のWebAPIにアクセスする場合、
--Access TokenをHTTPヘッダに指定して送信する。

***Access Tokenへの情報格納方法 [#l465fe76]
ClaimsIdentityを使用する。以下のようなURN形式をkeyに使用してvalueの追加を行う。

-"scope=auth"の場合(Access Tokenが[[ユーザ認証>#tf864e14]]用であることを意味する。詳しくは[[下記>#oa657de9]]参照)
 claimsIdentity.AddClaim(new Claim("urn:oauth:auth", client_id));
-"scope=その他の値"の場合、
 claimsIdentity.AddClaim(new Claim("urn:oauth:scope", scope));

**クライアント認証 [#u994461a]
ここでのクライアントとは、[[OAuth>https://techinfoofmicrosofttech.osscons.jp/index.php?OAuth]] 2.0 のClientを指しているので注意する。

-認可エンドポイントでは、クライアント認証ではなく、Redirectエンドポイントの検証を行う。
-クライアント認証は、Tokenエンドポイントにアクセスする際に行なう。
-ベーシック認証の認証ヘッダを使用して[[クライアント識別子>#bd77b31a]]を送信する。

***[[クライアント識別子>#bd77b31a]] [#hb59710b]
-GUIDを使用する
--32文字の英数字。
--URLに指定するので、[{}, -] は無し。

-client_id~
全てのグラント種別以外で必須
-client_secret
--Implicitグラント種別以外で必須
--ただし、[[ユーザ認証>#tf864e14]]で使用する場合は、Implicitグラント種別でも必須。

**ユーザ認証 [#tf864e14]
-ユーザ認証に利用する場合、以下の仕様に準拠する。
-[[クライアント識別子>#bd77b31a]]は全てのグラント種別で必須

***Server側 [#oa657de9]
-AuthorizationServer
--Tokenエンドポイント(Access Tokenの発行方法)
---scope=authの場合、client_idをClaimに格納し、Access Tokenがユーザ認証用であることを明示する。

-ResourceServer
--ユーザ認証専用のWebAPIを提供する。
---"urn:oauth:auth"のClaimがあった場合、Access Tokenがユーザ認証用であることを意味する。
---この場合、POSTされた[[クライアント識別子>#bd77b31a]]でクライアント認証をした後、~
そのClaim値とclient_idを比較してTokenに問題がないかをチェックする。

***Client側 [#x001826d]
-グラント種別
--できるだけ、Authorization Codeグラント種別を使用する。
--Implicitグラント種別もサポートするが、その場合、~
ユーザ認証用Access Tokenと[[クライアント識別子>#bd77b31a]]の露見のリスクがあることに注意すること。

-パラメタ
--response_typeには、"code"(推奨) or "token"を指定する。
--ユーザ認証を行なう場合、scopeパラメタに"auth"を指定する。

-ResourceServerのユーザ認証専用のWebAPIにアクセスする場合、
--ユーザ認証用Access Tokenに加え、前述の[[クライアント識別子>#bd77b31a]]をPOSTで送信する。

***ResourceServerのWebAPI [#u68a575d]
-認証専用のWebAPI
--/api/OAuthResourceApi/GetAuthenticatedUsersClaim

-リソース・アクセス用のWebAPI
--/api/OAuthResourceApi/XXXXX

**動作検証 [#jcf369d6]
**パラメタ化 [#k2595218]

***Authorization Codeグラント種別 [#w8d19e13]
「http://localhost:XXXXX/home/index」で表示されるAuthorization Codeグラント種別のテスト用linkをclickする。
***共通設定 [#lcf9fd19]
 <add key="EquipOAuthServer" value="true" />
 <add key="OAuthIssuerId" value="IssuerId:サイト毎にGUIDの32文字を生成して設定" />
 <add key="AllowOAuthInsecureHttpEndpoints" value="true" />
 <add key="OAuthAuthorizeEndpointCanDisplayErrors" value="true" />
 <add key="OAuthAccessTokenExpireTimeSpanFromMinutes" value="360" />

***Implicitグラント種別 [#v8c5ac21]
「http://localhost:XXXXX/home/index」で表示されるImplicitグラント種別のテスト用linkをclickする。
***Server側エンドポイント [#o0322317]
Multi-AuthSystemが保有するエンドポイントなで、相対パスで良い。

***Resource Owner Password Credentialsグラント種別 [#ka3a0c97]
-[[cURLコマンド]]を使用して認証専用WebAPIへのアクセスを検証する。
--認証の拡張仕様の部分は、&color(red){朱書き};にしてある。
--通常のリソース用WebAPIへのアクセス時はこのパラメタの指定は不要。
 <!-- 認可エンドポイント -->
 <add key="OAuthAuthorizeEndpoint" value="/Account/OAuthAuthorize" />
 <!-- Tokenエンドポイント -->
 <add key="OAuthBearerTokenEndpoint" value="/OAuthBearerToken" />
 <!-- ResourceServerエンドポイント -->
 <add key="OAuthAuthenticateAPI" value="/api/OAuthResourceApi/Authenticate" />
 <add key="OAuthAuthorizedUserClaimAPI" value="/api/OAuthResourceApi/GetAuthorizedUserClaim" />

-処理の概要
***Client側エンドポイント [#dd6249b1]
Clientだが、Multi-AuthSystemが保有する[[セルフRedirectエンドポイント>#bc429bf4]]なので、相対パスで良い。

--Tokenエンドポイントに対して以下のRequestを出すと、Bearer Tokenが返ってくる。
---POST
---Authorization: Basic ZZZZZZZZZZ ---> 「クライアントID:クライアント・パスワード」をBase64エンコードしたもの。
---body : grant_type=password, username=ユーザID, password=ユーザ・パスワード, &color(red){scope=auth};
 <!-- Redirectエンドポイント -->
 
 <!--  - self_code : Authorization Codeグラント種別 -->
 <add key="OAuthAuthorizationCodeGrantClient" value="/Account/OAuthAuthorizationCodeGrantClient" />
 
 <!--  - self_token : Implicitグラント種別 -->
 <add key="OAuthImplicitGrantClient" value="/Account/OAuthImplicitGrantClient" />

--Bearer Tokenをヘッダに指定して認証専用のWebAPIにアクセスすると認証情報を取得できる。
---POST
---Authorization: Bearer XXXXXXXXXX
---body : &color(red){client_id=クライアントID, client_secret=クライアント・パスワード};
***[[クライアント認証用の識別子登録>#u994461a]] [#nd32db3d]
 <!-- クライアント識別子 (client_id, client_secret, redirect_uri) -->
 <add key="OAuthClientsInformation" value='
   {
     "client_idとしてサイト毎にGUIDの32文字を生成して設定": {
    "client_secret": "サイト毎にGUIDの32文字を生成して設定",
    "redirect_uri": "self_code"
     },
     "client_idとしてサイト毎にGUIDの32文字を生成して設定": {
    "client_secret": "サイト毎にGUIDの32文字を生成して設定",
    "redirect_uri": "self_token"
     },
     "client_idとしてサイト毎にGUIDの32文字を生成して設定": {
    "client_secret": "サイト毎にGUIDの32文字を生成して設定",
    "redirect_uri": "self_token_web"
     },
     "client_idとしてサイト毎にGUIDの32文字を生成して設定": {
    "client_secret": "サイト毎にGUIDの32文字を生成して設定",
    "redirect_uri": "self_token_mob:アプリ間連携用URI"
     },
     "client_idとしてサイト毎にGUIDの32文字を生成して設定": {
    "client_secret": "サイト毎にGUIDの32文字を生成して設定",
    "redirect_uri": "http://hogehoge/・・・"
     },
    ・・・
   }
   ' />

-[[cURLコマンド]]~
Debug ProxyにFiddler等を使用すると尚良(其の際は、 --proxy オプションを指定する必要がある)。
**セルフRedirectエンドポイント [#bc429bf4]
テスト用のRedirectエンドポイントだが、~
スマホネイティブの認証などでサイトを構築せず利用可能。

--Bearer Tokenの取得
***self_code [#m9dac4ff]
"redirect_uri": "self_code"

---Request (cURLコマンド)
 >curl "http://localhost:nnnnn/OAuthBearerToken"-u "クライアントID:クライアント・パスワード" -d "grant_type=password" -d "username=ユーザID" -d "password=ユーザ・パスワード" -d "scope=auth"
-Authorization Codeグラント種別を検証するRedirectエンドポイント。
-用途はテスト用(本番用には使用しないこと)
--Access TokenやRefresh Tokenを含むHTMLをreturnする。~
(あくまで検証用であり、本番ではTokenをreturnしないこと)
--サーバ側でResourceServerにアクセスした結果を含むHTMLをreturnする。

---Response (Body)
 {"access_token":"XXXXXXXXXX","token_type":"bearer","expires_in":nnnnn,"refresh_token":"YYYYYYYYYY"}
***self_token, self_token_web [#v210b617]
"redirect_uri": "self_token"~
"redirect_uri": "self_token_web"

--Bearer Tokenを使用したOAuthリソースへのアクセス
-Implicitグラント種別を検証するRedirectエンドポイント。
-用途はテスト用(本番用には使用しないこと)
--Access Tokenを含むHTML+JavaScriptをreturnする。

---Request (cURLコマンド)
 >curl "http://localhost:nnnnn/api/OAuthResourceApi/GetAuthenticatedUsersClaim" -H "Authorization: Bearer XXXXXXXXXX" -d "client_id=クライアントID" -d "client_secret=クライアント・パスワード"
***self_token_mob [#lb092cae]
"redirect_uri": "self_token_mob"

---Response (Body)
 {"userName":"XXXXX","email":"XXXXX","phoneNumber":"XXXXX"}
-Implicitグラント種別を検証するRedirectエンドポイント。
-用途はテスト用だけでなく、本番用も想定している。
--Access Tokenを含むHTML+JavaScriptをreturnし、~
事前登録したアプリ間連携用URIを使用してアプリ間でAccess Tokenを受け渡す。
--ネイティブ・アプリでは、コレを使用して認証・認可が可能。

***Client Credentialsグラント種別 [#h00dd765]
[[cURLコマンド]]を使用して動作を検証する。

-処理の概要

--Tokenエンドポイントに対して以下のRequestを出すと、Bearer Tokenが返ってくる。
---POST
Authorization: Basic ZZZZZZZZZZ ---> 「クライアントID:クライアント・パスワード」をBase64エンコードしたもの。
---body:grant_type=client_credentials

--Bearer Tokenをヘッダに指定して認証専用のWebAPIにアクセスすると認証情報を取得できる。
---POST
---Authorization: Bearer XXXXXXXXXX
---body : client_id=クライアントID, client_secret=クライアント・パスワード

-[[cURLコマンド]]~
Debug ProxyにFiddler等を使用すると尚良(其の際は、 --proxy オプションを指定する必要がある)。

--Bearer Tokenの取得

---Request (cURLコマンド)
 >curl "http://localhost:nnnnn/OAuthBearerToken" -u "クライアントID:クライアント・パスワード" -d "grant_type=client_credentials" -d "scope=auth"

---Response (Body)
 {"access_token":"XXXXXXXXXX","token_type":"bearer","expires_in":nnnnn,"refresh_token":"YYYYYYYYYY"}

--Bearer Tokenを使用したOAuthリソースへのアクセス

---Request (cURLコマンド)
 >curl "http://localhost:63359/api/OAuthResourceApi/GetAuthenticatedUsersClaim" -H "Authorization: Bearer XXXXXXXXXX" -d "client_id=クライアントID" -d "client_secret=クライアント・パスワード"

---Response (Body)
 {"userName":"XXXXX","email":"XXXXX","phoneNumber":"XXXXX"}


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS