「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -[[戻る>JWTとOAuth2.0#f5007063]] * 目次 [#m5c50d67] #contents *概要 [#a089122f] Tokenエンドポイントで、強化された~ クライアント認証を使用してaccess_tokenを取得する、~ -[[OAuth]] 2.0 を拡張するアサーションの仕様 -[[RFC 7521>#pae256bf]], [[7523>#i523cb7d]]によって構成されている。 -[[JWT]](JWS) Bearer Tokenを[[アサーション>トークン#xbeb945f]]として使用して、~ OAuth 2.0のAccess Tokenを要求する方法の定義。 *クライアント認証 [#y8528205] -本仕様自体がクライアント認証だとは思うが、~ 併用するクライアント認証はオプション(と言うかユースケースによる)。 -以下は、追加のクライアント認証が「[[無い場合>#f99e77d4]]」と「[[有る場合>#m4421be9]]」の概要説明。 **クライアント認証なしの場合 [#f99e77d4] ***概要 [#wb2404fe] -事前に信頼関係を構築できるシステムから~ ユーザによる認証・認可手順なしに直接Access Tokenを取得する。 -[[用例>#xd03a507]]にもあるGoogleやMicrosoft、~ SalesforceなどのWebAPI認証の方式として採用されている。 --クライアントと事前に鍵交換して、 --クライアントの[[Self-Issued Assertion>#n8fdd9f7]]で署名する。 ***フロー [#d21e8fa8] -[[JWT]](JWS)作成のための証明書を生成 or 取得する。 -証明書を登録する。 --Client側(秘密鍵) --Resource Server側(公開鍵) -Clientで[[JWT]](JWS)を署名し、Resource Serverにリクエスト、 -Resource Serverで[[JWT]](JWS)を検証し、Access Token(Bearer Token)をレスポンス。 -Clientから、Access Token(Bearer Token)を使用してResource Serverにアクセスする。 **クライアント認証ありの場合 [#m4421be9] ***概要 [#m8c572cd] -事前に信頼関係を構築できるシステムと、既存のユーザ承認フローの中で、~ 追加のクライアント認証をしてAccess Tokenを取得する。 ***フロー [#zb3d8932] こちらは、[[用例>#xd03a507]]では紹介されていないが、 -Authorization Codeグラント種別と併用するユースケース --[[ベース クライアント セキュリティ モデル]]的。 --「[[OIDCで追加のクライアント認証(JWT)をする場合>OpenID Connect#y7bdab62]]」のフローに近い。 -Client Credentialsグラント種別と併用するユースケース --[[サーバ信頼セキュリティ モデル]]的。 --「[[クライアント認証しない場合>#f99e77d4]]」のフローと大差ない。 などのユースケースのフローがある。 *仕様(7521) [#pae256bf] -単体では利用できず、[[RFC 7522, 7523のサブ仕様>#c65d5829]]の共通部分を抽象化した仕様。 -ClientとResource Serverを統合するような状況下での利用が想定されている。 --Resource Ownerとしてのエンド・ユーザの介入を必要としない。 --client_secretを必要としない(Client Credentialsグラント種別の)代替メカニズム。 **フレームワーク [#v20f3211] ↓、RPではなく、Authorization Serverなのでは?と思うが、~ 使い道に依り、あくまでクライアント認証に用いると考える。 ***Assertion Created by Third Party [#vf7e7da7] STSによってAssertionを生成する。 -フロー Relying Party Client Token Service | | | | | 1) Request Assertion | | |------------------------>| | | | | | 2) Assertion | | |<------------------------| | 3) Assertion | | |<-------------------------| | | | | | 4) OK or Failure | | |------------------------->| | | | | | | | -WS-Trust [OASIS.WS-Trust]などで利用されている。 ***Self-Issued Assertion [#n8fdd9f7] ローカルでAssertionを生成する。 -フロー Relying Party Client | | | | 1) Create | | Assertion | |--------------+ | | | | | 2) Assertion | | |<-------------+ | 3) Assertion | |<-------------------------| | | | 4) OK or Failure | |------------------------->| | | | | **アサーション [#h34941bb] これを使って[[アクセストークン・リクエスト>#a82c2f7a]]する。 ***文脈上 [#i1c8aa27] この文脈上でのアサーションは、 -Authorization Serverは、 --一般的に認可付与の短命表現で、~ アサーションの有効期間を越えるアクセストークンを発行すべきでない。 --アサーション許可要求に応答して ---リフレッシュトークンが発行せず、 ---アクセストークンを短い寿命で発行する。 -Clientは、 --同じアサーションを使用して新しいアサーションを要求したり、 --有効・若しくは新しいアサーションを使用して、~ 期限切れのアクセストークンをリフレッシュしたり、 >できる。 ***タイプ [#h0cefaa0] -Bearer Assertions --本仕様に適したタイプのアサーション --アサーションを所有しているすべてのエンティティは、 ---関連するリソースへのアクセスを取得するために(暗号鍵の所持を証明することなく)アサーションを使用できる。 ---誤用を防止するために、アサーションは、保管・移送における露見から保護する必要がある。 ---権限のない当事者にアサーションを漏らさないために、安全な通信チャネルを使用。 -Holder-of-Key Assertions --本仕様に適さないタイプのアサーション(だったら書くな。と、) --アサーションを提示するエンティティは、 ---関連するリソースにアクセスするには、 ---追加の暗号資料の所持を証明する必要がある。 --従って、 ---Authorization Server(STS)は、アサーションにキー識別子をバインドする。 ---Clientは、アサーションを提示するときに、~ その識別子に対応するキーを知っていることをResource Serverに示す必要がある。 --鍵所有者アサーションシステムのベースラインとして使用することができるが、場合によっては、以下が必要になる。 ---(秘密鍵の所有証明をサポートするための)追加のメカニズム ---セキュリティモデルの変更(例えば、 オーディエンスの要件を緩和するため)。 ***クレームセット [#p574a133] 以下のクレームが必要。 [[IDトークン>OpenID Connect#ofb73c59]]が参考になる。 -必須 --Issuer ---[[Assertion Created by Third Party>#vf7e7da7]]の場合、~ Authorization Server(STS)のIDになる。 ---[[Self-Issued Assertion>#n8fdd9f7]]の場合、~ Audienceの値と同じになる。 --Subject ---[[サーバ信頼セキュリティ モデル]]~ Audienceの値と同じになる。 ---[[ベース クライアント セキュリティ モデル]]~ Resource OwnerのIDの値と同じになる。 --Audience~ Resource ServerのID = client_idの値 --Expires At -オプション --Issued At --Assertion ID~ アサーションの一意の識別子。 ---他のエンティティが誤って同じ識別子を割り当てないことを保証しなくてはならない。 ---ワンタイム使用アサーションのメッセージ重複排除を必要とする実装によって使用される可能性がある。 --[[クライアント認証なし>#f99e77d4]] ---scope~ [[クライアント認証なし>#f99e77d4]]=[[Googleの例>#f5ac0fc6]]など、~ 追加のクライアント認証を使用しない場合、scopeが必要になる。 --[[クライアント認証あり>#m4421be9]] ---・・・ ***署名 [#h4756c73] -署名またはメッセージ認証コードを生成する -アルゴリズムは任意(この仕様の範囲外) **パラメタ [#aed15519] -TLS(Transport Layer Security)が必須。 -アサーションの認可付与としての使用を定義。 ***grant_type [#eef72461] -[[クライアント認証なし>#f99e77d4]]~ urn:ietf:params:oauth:grant-type:* --urn:ietf:params:oauth:grant-type:saml2-bearer --urn:ietf:params:oauth:grant-type:jwt-bearer -[[クライアント認証あり>#m4421be9]]~ 既存のフローのクライアント認証(HTTP Basic 認証スキーマ)を使用する。 --grant_type=client_credentials --grant_type=authorization_code authorization_codeなので、codeも必要(code=XXXX) ***scope [#x0b3b1ff] 要求された範囲は、[[OAuth 2.0 [RFC6749]>OAuth#v698197b]]の3.3節に記述されているとおり。 -[[クライアント認証なし>#f99e77d4]]~ [[Googleの例>#f5ac0fc6]]など、追加のクライアント認証を使用しない場合、 --(パラメタとしては、)不要 --[[クレームセット>#p574a133]]中には必要になる。 -[[クライアント認証あり>#m4421be9]] --既存のフローのクライアント認証を使用する。 --従って、この場合は、スターターでQuery Stringにscopeを指定。 --[[クレームセット>#p574a133]]中からは不要になる。 ***client_id [#c3be6c2e] パラメタに依存するクライアント認証の形式が使用されている場合にのみ必要。 -[[クライアント認証なし>#f99e77d4]]~ --(パラメタとしては、)不要 --[[クレームセット>#p574a133]]中には必要になる(client_id = aud = sub)。 -[[クライアント認証あり>#m4421be9]] --既存のフローのクライアント認証を使用する。 --従って、この場合は、client_idを指定。 --[[クレームセット>#p574a133]]中には必要になる。 ---[[サーバ信頼セキュリティ モデル]]:client_id = aud = sub ---[[ベース クライアント セキュリティ モデル]]:client_id = aud ***assertion [#k4e1e004] -[[クライアント認証なし>#f99e77d4]]~ [[RFC7523>#i523cb7d]]のアサーションを参照。 -[[クライアント認証あり>#m4421be9]]~ 不要 ***client_assertion_type [#y8e7d02b] -[[クライアント認証なし>#f99e77d4]]~ 不要 -[[クライアント認証あり>#m4421be9]]~ urn:ietf:params:oauth:grant-type:* --urn:ietf:params:oauth:grant-type:saml2-bearer --urn:ietf:params:oauth:grant-type:jwt-bearer ***client_assertion [#d6680711] -[[クライアント認証なし>#f99e77d4]]~ 不要 -[[クライアント認証あり>#m4421be9]]~ [[RFC7523>#i523cb7d]]のアサーションを参照。 **リクエスト・レスポンス [#u7d06247] ***アクセストークン・リクエスト [#a82c2f7a] -[[クライアント認証なし>#f99e77d4]] --ヘッダ POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded --ボディ grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3AX-bearer& assertion=SAML2 or JWT assertion -[[クライアント認証あり>#m4421be9]] --grant_type=authorization_code版 ---ヘッダ POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded ---ボディ grant_type=authorization_code& code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4& client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3AX-bearer& client_assertion=SAML2 or JWT assertion --grant_type=client_credentials版 ---ヘッダ POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded ---ボディ grant_type=client_credentials& client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3AX-bearer& client_assertion=SAML2 or JWT assertion ***アクセストークン・レスポンス [#m7f17c23] 仕様中に明記なし。 ***エラー・レスポンス [#u137f3a9] -[[OAuth 2.0 [RFC6749]>OAuth#v698197b]]で定義されているエラー応答を構成 --https://tools.ietf.org/html/rfc6749#section-5.2 -[[クライアント認証なし>#f99e77d4]]~ アサーションが有効でないか期限が切れた場合、 --Authorization Serverは、 ---"error"パラメータの値は "invalid_grant"エラーコードでなければならない。 ---"error_description"または "error_uri"パラメータを使用して、~ アサーションが無効とみなされた理由に関する追加情報を含めることができる。 --例 ---ヘッダ HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store ---ボディ { "error":"invalid_grant", "error_description":"Audience validation failed" } -[[クライアント認証あり>#m4421be9]] --Authorization Serverは、 ~ アサーションが有効でないか複数のクライアント認証メカニズムが使用されている場合、 ---"error"パラメータの値は "invalid_client"エラーコードでなければならない。 ---"error_description"または "error_uri"パラメータを使用して、~ クライアントのアサーションが無効であると考えられた理由に関する追加情報を含めることができる。 --例 ---ヘッダ HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store ---ボディ { "error":"invalid_client" "error_description":"assertion has expired" } **セキュリティに関する考慮事項 [#c569fe33] -[[RFC 7522, 7523>#c65d5829]]などを使用すれば、大方問題ない。 -その他、 --SSL/TLSを使用する。 --Assertion IDを実装する。 *仕様(7523) [#i523cb7d] [[RFC 7521>#pae256bf]]のアサーションに[[JWT(JWS)アサーション>#s121ce30]]を使用したもの。 **[[JWT]](JWS)アサーション [#s121ce30] これを使って[[アクセストークン・リクエスト>#yf148536]]する。 ***ペイロード(クレームセット) [#od912bf1] -[[コチラ>#p574a133]]を参考に、 -必須(MUST) --"iss" (issuer) claim --"aud" (audience) claim --"sub" (subject) claim --"exp" (expiration time) claim~ -してもよい(MAY) --"iat" (issued at) claim --"jti" (JWT ID) claim~ = Assertion ID --"nbf" (not before) claim~ トークンを受け入れてはならない前の時間を識別する。 ***[[JWT]](JWS)の例 [#f5ac0fc6] -以下、RFCの[[JWT]](JWS)~ よくよく確認すると、URLはなに?(Scheme?) --ヘッダ {"alg": "ES256"、 "kid": "16"} --ペイロード { "iss":"https://jwt-idp.example.com", "sub":"mailto:mike@example.com", "aud":"https://jwt-rp.example.net", "nbf":1300815780, "exp":1300819380, "http://claims.example.com/member":true } -以下、Googleの[[JWT]](JWS)~ よくよく確認すると、subが無かったりする。 --ヘッダ { "alg": "RS256", "typ": "JWT" } --ペイロード { "iss":"サービスアカウントのメールアドレス", "scope":"利用するAPIのスコープ", "aud":"https://www.googleapis.com/oauth2/v3/token", "exp":"トークンの有効期限To", "iat":"トークンの有効期限From", } **パラメタ [#jab8a61d] -[[仕様(7521)のパラメタ>#aed15519]]と同じ。 -client_assertionだけ、以下のような注釈有リ。 --1つの[[JWT]](JWS)、複数の[[JWT]](JWS)を含んではならない。 **リクエスト・レスポンス [#ne5367ec] ***アクセストークン・リクエスト [#yf148536] -[[クライアント認証なし>#f99e77d4]] --ヘッダ POST /token.oauth2 HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded --ボディ grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer& assertion=...JWS... -[[クライアント認証あり>#m4421be9]] --ヘッダ POST /token.oauth2 HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded --ボディ grant_type=authorization_code& code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4& client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer& client_assertion=...JWS... ***アクセストークン・レスポンス [#o199c57d] 仕様中に明記がないが、Googleでのレスポンスは以下の通り。 { "access_token":"XXXXXXXXXX", "token_type":"bearer", "expires_in":nnnnn } ※ ポイント : refresh_tokenを返さない。 ***エラー・レスポンス [#n2b1c5ca] [[仕様(7521)のエラー・レスポンス>#u137f3a9]]と同じ。 **署名アルゴリズム [#feca38aa] 本仕様中に記載はないが、[[コチラ>OpenID Connect#cee38fe3]]を参考にするとイイ。 *参考 [#uea38a81] **RFC 7521, 7522, 7523 [#c65d5829] -RFC 7521 - Assertion Framework for~ OAuth 2.0 Client Authentication and Authorization Grants~ https://tools.ietf.org/html/rfc7521 --RFC7522(SAMLアサーション) ---RFC 7522 - Security Assertion Markup Language (SAML) 2.0 Profile~ for OAuth 2.0 Client Authentication and Authorization Grants~ https://tools.ietf.org/html/rfc7522 --RFC7523(JWTアサーション) ---RFC 7523 - JSON Web Token (JWT) Profile~ for OAuth 2.0 Client Authentication and Authorization Grants~ https://tools.ietf.org/html/rfc7523 **用例 [#xd03a507] ***Googleの例 [#pe004c1a] 以下を見ると、 -C#とCoreTweetを使って簡単にTwitterへツイートするbotを作る - 酢ろぐ!~ http://blog.ch3cooh.jp/entry/20140808/1407464147 --Google Analytics API を使って前日の PV を取得するコードを C# で書いてみた - しばやん雑記~ http://blog.shibayan.jp/entry/20140803/1407059293 通常の[[OAuth]] 2.0の -[[Authorization Codeグラント種別>OAuth#yfeb403d]] -[[Implicitグラント種別>OAuth#m5c2d510]] 以外に、 [[クライアント証明書(pfx形式の電子証明書)>証明書#sd119f77]]を使って、~ サービスアカウントで認証する方法がある模様。 ちなみに、ここでは、Google.Apis.Analytics Client Libraryに~ 処理がラッピングされていたため。詳細が不明だったが、 以下を見ると、このClient Libraryの中では、[[JWT]]が使用されている模様。 -JWTを使ってGoogleAPIのアクセストークン取得する - Carpe Diem~ http://christina04.hatenablog.com/entry/2015/06/04/224159 -IdM実験室: [JWT/OAuth]Service Accountを使ってGoogle APIを利用する --http://idmlab.eidentity.jp/2015/01/jwtoauthservice-accountgoogle-api.html --http://idmlab.eidentity.jp/2015/01/jwtoauthservice-accountgoogle-api_5.html これが、 >「JWT bearer token authorizationグラント種別」 の用例である模様。 -GoogleのOAuth 2.0実装からみえたClientの扱い - r-weblife~ http://d.hatena.ne.jp/ritou/20121104/1352036133 上記のサイトには、 >Service Accounts = JWT Bearer Token Profile であることが明記されている。 ***Microsoft ([[AzureAD>Microsoft Azure Active Directory]]) の例 [#vdf678b9] [[Google>#pe004c1a]]と同様に、以下を見ると、 -Azure AD : ログインをしない Backend Server-Side アプリの開発 (Daemon など) – Tsmatz~ https://blogs.msdn.microsoft.com/tsmatsuz/2015/04/09/azure-ad-backend-server-side-deamon-service/ -Azure ADに登録されているAPI用のアクセストークンをJWTで取得するには | hrendoh's memo~ http://blog.hrendoh.com/active-directory-dotnet-daemon-certificate-credential/ --Authenticating to Azure AD in daemon apps with certificates | Microsoft Azure~ https://azure.microsoft.com/ja-jp/resources/samples/active-directory-dotnet-daemon-certificate-credential/ 通常の[[OAuth]] 2.0の -[[Authorization Codeグラント種別>OAuth#yfeb403d]] -[[Implicitグラント種別>OAuth#m5c2d510]] 以外に、 >「JWT bearer token authorizationグラント種別」 をサポートしている模様。 ただし、処理は、[[ADAL(Active Directory Authentication Library)>https://docs.microsoft.com/ja-jp/azure/active-directory/develop/active-directory-authentication-libraries]]~ にラップされているため[[JWT]]作成処理の詳細などを見ることは出来ない。 -active-directory-dotnet-daemon-certificate-credential/Program.cs~ at master · Azure-Samples/active-directory-dotnet-daemon-certificate-credential~ https://github.com/Azure-Samples/active-directory-dotnet-daemon-certificate-credential/blob/master/TodoListDaemonWithCert/Program.cs ***Salesforceの例 [#w40dd954] 以下のQiita記事を参照すると、Salesforceは、 -OAuth 2.0 JWT べアラートークンフロー -OAuth 2.0 SAML ベアラーアサーションフロー の2つのフローをサポートしている模様。 -OAuth2 JWT Bearer Token フローを使ってSalesforceへアクセスする - Qiita~ http://qiita.com/stomita/items/4542ce1b48e5fa849ef1 --help.salesforce. ---OAuth 2.0 JWT べアラートークンフロー~ https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&language=ja&type=0 ---OAuth 2.0 SAML ベアラーアサーションフロー~ https://help.salesforce.com/articleView?id=remoteaccess_oauth_SAML_bearer_flow.htm&language=ja&type=0 >原理はほぼ同じで、[[SAML]]より[[JWT]]のほうが動作環境的な制約は少ないとのこと。 ---- Tags: [[:認証基盤]], [[:クレームベース認証]], [[:OAuth]]