「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
- このページは、ドラフト 15 を参考にして作成。
- F-API2でのユースケースは限定的で分かり易いが、
こちらのフルスペックは若干意味不明(私が理解できていないダケ)。
弱点 †
以下の弱点のために、
- TLS末端は保護されないため、パラメタ汚染、通信監視が可能。
- TLSセッションは、UserAgent?で終了する。
- TLSセッションは、ロードバランサなど(ミドルボックス)で時期尚早に終了することがある。
攻撃 †
以下の攻撃が可能。
- Redirect URI書き換え攻撃
- ミックスアタック攻撃[FETT]
対策 †
対策として、認可リクエストのパラメタ群をJWTで送信する
(認証要求に署名し、オプションで暗号化できる。)
本OAuth 2.0 拡張がOpenID Connectによって追加された。
効果 †
このアプリケーション層セキュリティの使用により、
- 許可要求の機密性、完全性が達成され、
- これらの問題が緩和される。
サード・パーティー †
本仕様(コンテキスト)中で、「サード・パーティー」という用語は、以下に関連する。
Requestオブジェクト †
内容 †
JWT化された認可リクエストのパラメタ群をRequestオブジェクトと呼ぶ。
生成方法 †
効果 †
- 合意した以上のアクセス権を要求できないようにすることで、プライバシーを保護する。
- この場合、認可プロンプトをスキップすることが望ましい場合もある。
- 以下のような少数例にも適合する。
- 送信される要求のサイズを小さくすることが望ましい場合(秘密鍵?)。
- Clientが暗号を行いたくないとき(JWSで署名し、TLSを使用する)。
クレームセット †
Requestオブジェクト(JWT)のペイロードをbase64urlデコードした文字列。
認可Requestの全てのパラメタがRequestオブジェクトに同梱されている。
- ペイロード
※ nonceやmax_ageなどの拡張変数が含まれる。
- 通常
{
"iss": "s6BhdRkqt3",
"aud": "https://server.example.com",
"response_type": "code id_token",
"client_id": "s6BhdRkqt3",
"redirect_uri": "https://client.example.org/cb",
"scope": "openid",
"state": "af0ifjsldkj",
"nonce": "n-0S6_WzA2Mj",
"max_age": 86400
}
- claimsリクエスト・パラメタを含む。
{
"iss": "s6BhdRkqt3",
"aud": "https://server.example.com",
"response_type": "code id_token",
"client_id": "s6BhdRkqt3",
"redirect_uri": "https://client.example.org/cb",
"scope": "openid",
"state": "af0ifjsldkj",
"nonce": "n-0S6_WzA2Mj",
"max_age": 86400,
"claims": {
"userinfo": {
"given_name": {
"essential": true
},
"nickname": null,
"email": {
"essential": true
},
"email_verified": {
"essential": true
},
"picture": null
},
"id_token": {
"gender": null,
"birthdate": {
"essential": true
},
"acr": {
"values": [
"urn:mace:incommon:iap:silver"
]
}
}
}
}
公開鍵 †
署名を検証する場合、JWK形式で表されるRSA公開鍵を使用する。
※ jwks_uriにJWK Setを公開する。
{
"kty":"RSA",
"kid":"k2bdc",
"n":"y9Lqv4fCp6Ei-u2-ZCKq83YvbFEk6JMs_pSj76eMkddWRuWX2aBKGHAtKlE5P
7_vn__PCKZWePt3vGkB6ePgzAFu08NmKemwE5bQI0e6kIChtt_6KzT5OaaXDF
I6qCLJmk51Cc4VYFaxgqevMncYrzaW_50mZ1yGSFIQzLYP8bijAHGVjdEFgZa
ZEN9lsn_GdWLaJpHrB3ROlS50E45wxrlg9xMncVb8qDPuXZarvghLL0HzOuYR
adBJVoWZowDNTpKpk2RklZ7QaBO7XDv3uR7s_sf2g-bAjSYxYUGsqkNA9b3xV
W53am_UZZ3tZbFTIh557JICWKHlWj5uzeJXaw",
"e":"AQAB"
}
渡し方 †
Requestオブジェクトの渡し方にはrequestとrequest_uriの2つのパラメタを使用する方法がある。
- requestとrequest_uriパラメタを、OAuth 2.0 の追加の認証要求パラメタとして導入。
- パラメタは「application/x-www-form-urlencoded = QueryString?」として渡す。
requestパラメタ †
Requestオブジェクトの値を直接渡す。
request_uriパラメタ †
※ この場合、response_type, client_id, state値の同梱が必要。
(下位互換などのため、)QueryString?に同じパラメタが指定できるダケ。
- request_uriエンドポイント
通常は、ローカルの検索ではなく、HTTPのRequestを行う。
- Response
HTTP/1.1 200 OK
Date: Thu, 16 Feb 2017 23:52:39 GMT
Server: Apache/2.2.22 (tfp.example.org)
Content-type: application/jwt
Content-Length: 1250
Last-Modified: Wed, 15 Feb 2017 23:52:32 GMT
ey・・・(JWT)・・・
実装 †
下記手順で取得したRequestオブジェクトを署名検証(若しくは復号)する。
サード・パーティー †
この章に書かれている「jwks_uriにJWK Setを公開」する実装例は、
- サード・パーティーに依る「Assertion Created by Third Party」実装の場合か?
- Clientに依る場合、「Self-Issued Assertion」実装で良い気がする。
復号化 †
Requestオブジェクトが暗号化されている場合、
下記手順で取得したRequestオブジェクトを復号化する。
復号化の処理 †
- Requestオブジェクトの復号用の鍵を取得。
クライアント・メタデータの登録・有無によってシーケンスが異なる。
- 登録されている場合、
JWK Setをjwks クライアントメタデータ値から取得。
- 登録されていない場合、
jwks_uriからクライアント・メタデータ(JWK Set)を取得。
- Requestオブジェクトを復号化して、
- 認可エンドポイントへのパラメタ
- 若しくは、Requestオブジェクト(署名)
を取り出す。
復号化の失敗 †
復号化に失敗した場合、Authorization Serverは
「invalid_request_object」エラーを返す。
署名検証 †
下記手順で取得したRequestオブジェクトを署名検証する。
署名検証の処理 †
- Requestオブジェクトの署名・検証用の鍵を取得。
クライアント・メタデータの登録・有無によってシーケンスが異なる。
- 登録されている場合、
JWK Setをjwks クライアントメタデータ値から取得。
- 登録されていない場合、
jwks_uriからクライアント・メタデータ(JWK Set)を取得。
- Requestオブジェクトから認可エンドポイントへのパラメタを取り出す。
署名検証の失敗 †
署名検証に失敗した場合、Authorization Serverは「invalid_request_object」エラーを返す。
パラメタ検証 †
Authorization Serverは、
- (下位互換などのため、)QueryString?に同じパラメタが指定することもできる。
しかし、パラメタ検証には、Requestオブジェクト内のパラメタのみを使用しなければならない。
- 次にOAuth 2.0 [RFC6749]で指定された要求を検証する。
追加エラー値 †
requestパラメタ †
- request_not_supported
Authorization Serverは、requestパラメタの使用をサポートしない。
- invalid_request_object
requestパラメタに無効なRequestオブジェクトが含まれている。
request_uriパラメタ †
- request_uri_not_supported
Authorization Serverは、request_uriパラメタの使用をサポートしない。
- invalid_request_uri
request_uriパラメタに対する要求が、エラーか、無効なRequestオブジェクトを返す。
TLS要件 †
TLSをサポートしなければならない。
- 秘密性と完全性の保護を提供し、情報の漏えいや改ざんから保護する。
- man-in-the-middle攻撃を防ぐため、DNS-ID識別子を使用して、サーバ証明書を検証。
サーバ証明書要件 †
- サーバ証明書のDNS名にワイルドカード文字「*」を含めることができる
- DNS-ID識別子タイプ(つまり、subjectAltName?拡張子のdNSName ID)のサポートが必須
- サーバ証明書を発行する認証機関はDNS-ID識別子タイプをサポート
- DNS-ID識別子タイプはサーバ証明書に存在しなければならない
その他 †
- クライアントはCN-ID識別子を(認証に)使用してはならない。
- SRV-IDとURI-IDは、比較のために使用してはならない。
セキュリティに関する考慮事項 †
ソース認証 †
認可リクエストの送信元は常に検証されなければならない。
Requestオブジェクトの暗号処理 †
- Requestオブジェクトの署名検証を行う。
- Requestオブジェクトの復号用の秘密鍵が正しいか。
request_uriとサーバ証明書 †
request_uriのサーバ証明書のIDを帯域外で知っている必要がある
(ただし、これは、一般的に信頼された方法ではない(ので後述が推奨?))。
request_uriとclient_idのバインド †
Authorization Serverは、
- 受け入れたRequestオブジェクト中の、
request_uriとclient_idをバインドするクライアント認証が必要。
- このため、POSTされたRequestオブジェクトと引き換えに、
request_uriを提供するエンドポイントを提供できる。
- (以下を参照すると、恐らく、)ココのエンドポイントで何らかのクライアント認証を行う。
- 返した、request_uriを使用すると、client_idを含むRequestオブジェクトを取得できる。
- この場合の、request_uriの要件は、
- 有効期間は短く、好ましくはワンタイムにする必要がある。
- また、エントロピーは十分に大きくなければならない。
- これらは、保護されるリソースの価値に依存するが、
一般的なガイダンスは、以下の通り。
- 有効時間の1分未満。
- 128bit以上の暗号ランダム値を含める。
※ FAPI Part 2に実例がある。
Trust Framework Provider †
上記エンドポイントがサード・パーティーのTrust Framework Providerによって提供されても良い。
エンドポイント間のリンク †
以下のエンドポイント間のリンクを張る拡張仕様が必要。
([FETT]で紹介されたクロスフェーズ攻撃を防止する)
- 認可エンドポイント( "authorization_endpoint")
- Redirect URI( "redirect_uri")
- Tokenエンドポイント( "token_endpoint")
- 保護されたリソース( "protected_resources")
request_uri関連のリスク †
DDoS攻撃 †
- 不正なクライアントが、不正な"request_uri"を指定する。
- この場合、以下の攻撃が可能になる。
- 非常に大きなコンテンツを返す。
- 非常に遅く応答する。
- 再帰的GETを引き起こす。
Request URI Rewrite †
- request_uriパラメタの値は署名されていないため、
man-in-the-middle攻撃によって、改ざんされる可能性がある。
- この場合、以下の攻撃が可能になる。
- 書き換えられたURIが指し示す別のファイルを作成して、余分なscopeを要求できる。
- 「request_uri」の値を犠牲者の値に設定することによって、DoS攻撃を開始する。
(再帰的GETもできそうだが・・・?)
対策 †
- request_uriパラメタの値が予期しない場所を指していないこと。
- 応答のコンテンツタイプが、"application/jwt"であること。
- request_uriの内容を取得するためのタイムアウトを実装すること。
- request_uriに対する再帰的GETを実行しないこと。
プライバシーに関する考慮事項 †
RFC6973
コレクションの制限 †
個人情報保護法のため、個人情報を含む場合、厳密にscopeを制限するべき。
- Clientは、登録リクエスト行う。
- Authorization Serverは、
- request_uriがTrust Framework Providerのモノか検証する。
- HTTP GET要求をrequest_uriに発行する。
- TLS証明書のサーバIDがrequest_uriと一致するか確認する。
- Clientを表す「client_id」を含むRequest Objectを取得する。
開示の制限 †
リクエストの開示 †
- 問題
- この仕様は、拡張パラメタを許可し、ここに機密情報が含まれる可能性がある。
- 特にRefererとBrowser履歴を介して、Querystringから漏洩する可能性がある。
- 対策
- requestパラメタ
Requestオブジェクトに機密性の高いパラメタが含まれている場合、
ClientはRequestオブジェクトをJWEで暗号化すべき。
ユーザ毎のrequest_uriは避けるべき。 †
- 永続的なユーザ単位のrequest_uriが使用されている場合、ユーザを識別することが可能。
- ブラウザの履歴などでコレを観察し、ユーザ活動との関連付けが可能。
- ある意味では、これはデータ開示でもあり、避けるべき。
参考 †
Tags: :IT国際標準, :認証基盤, :クレームベース認証, :OAuth