[2] [[OAuth 2.0]] の[DFN[[RUBYB[[[クライアント認証]]]@en[client authentication]]]]は、[[クライアント]] ([[Web API]]
にアクセスする外部サービス) に関して[[認可サーバー]]が[[認証]]するものです。

* 仕様書

[REFS[
- [201] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749>
-- [34] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-3.2>
-- [52] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.1.3>
-- [61] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.3.2>
-- [65] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.4.2>
-- [1] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-6>
-- [21] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-9>
-- [89] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-10>
- [97] [CITE[RFC Errata Report]] ([TIME[2015-02-16 00:47:02 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=6749>
- [109] [CITE@en[Final: OpenID Connect Core 1.0 incorporating errata set 1]] ([TIME[2014-11-09 04:00:29 +09:00]] 版) <http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication>
- [4] [CITE@en[RFC 7521 - Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants]] ([TIME[2015-05-28 13:43:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7521#section-4.2>
- [8] [CITE@en[RFC 7591 - OAuth 2.0 Dynamic Client Registration Protocol]] ([TIME[2015-07-15 00:25:14 +09:00]] 版) <https://tools.ietf.org/html/rfc7591#section-4.2>
- [7] [CITE[OAuth Parameters]] ([TIME[2015-09-18 05:35:53 +09:00]] 版) <http://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method>
]REFS]

* 文脈

[43] [[クライアント型]]が[[機密]]の[[クライアント]]と、
[[クライアントcredentials]]を発行された[[クライアント]]は、
[[トークンエンドポイント]]への[[要求]]で[[クライアント認証]]を行わなければ[['''なりません''']]
[SRC[>>34, >>52, >>61, >>65, >>1]]。
ただし[[ネイティブアプリケーション]]は、
[[認可符号]]フローにおいて[[クライアント]]の [[credentials]]
を送信する[['''べきではありません''']] [SRC[>>21]]。

[49] [[クライアント型]]が[[公開]]の[[クライアント]]は、(以上に該当しなくても) 
[[トークンエンドポイント]]への[[要求]]で自身を識別する
[CODE(URI)@en[[[client_id]]]] [[引数]]を使っても構いません [SRC[>>34, >>97]]。

;; この場合は [[credentials]] は指定しないので、[[クライアント認証]]は行われません。

[98] なおこの[[クライアント認証]]は、[[トークンエンドポイント]]の他、
[[revokeエンドポイント]]でも使われます。

* 処理

[82] [[認可鯖]]は、[[クライアント型]]が[[機密]]の[[クライアント]]や[[クライアントcredentials]]
を発行した[[クライアント]]に関しては、
[[トークンエンドポイント]]における [[OAuth 2.0]] の各[[承諾型]]の要求において、
[[クライアント認証]]を必須としなければ[['''なりません''']] [SRC[>>52, >>61, >>65, >>1, >>89]]。

[22] [[認可鯖]]は、[[クライアント型]]が[[機密]]の[[クライアント]]については、
自身の要件次第で任意の[[認証]]方式を使って[[認証]]して構いません [SRC[>>201]]。
[[認可鯖]]は、[[クライアント型]]が[[公開]]の[[クライアント]]についても[[認証]]して構いませんが、
[[クライアント]]の識別のためにこれに依存しては[['''なりません''']] [SRC[>>201]]。

;; [24] 一般的には[[合言葉]]や、[[公開鍵]]と[[秘密鍵]]の組のようなものを[[認可鯖]]が発行または登録して使います [SRC[>>201]]。[[クライアントの登録]]も参照。

[25] [[認可鯖]]は、
[[トークンエンドポイント]]における [[OAuth 2.0]] の各[[承諾型]]の要求に[[クライアント認証]]が含まれていれば、[[認証]]しなければ[['''なりません''']]
[SRC[>>52, >>61, >>65, >>1]]。

;; [23] [[OAuth 2.0クライアント認証]]は[[クライアント]]と[[認可鯖]]の間の任意の[[エンドポイント]]で利用可能な形で規定されてはいますが、実際に利用されるのは[[トークンエンドポイント]]でのみです。

* 認証方式

[3] 具体的な方式は、[[認可サーバー]]が決めることができます。複数の方法を提供する場合は、
その中から[[クライアント]]が選択できます。

[26] 複数の[[認証]]方法を単独の[[要求]]で併用しては[['''なりません''']] [SRC[>>201]]。

[110] [[OAuth 2.0]] 本体は[[認証]]方式に特に名前を与えていませんが、
[[RFC 7591]] [SRC[>>8]] や [[OpenID Connect]] は名前を定義 [SRC[>>109]] しています。
[[RFC 7591]] は[[IANA登録簿]]を規定しているので、いくつかは
[[IANA登録簿]] [SRC[>>7]] に登録されています。次の[[認証]]方式があります。

[FIG(short list)[
- [CODE@en[[[client_secret_basic]]]]
- [CODE@en[[[client_secret_post]]]]
- [CODE@en[[[client_secret_jwt]]]]
- [CODE@en[[[private_key_jwt]]]]
- [CODE@en[[[none]]]]
]FIG]

[27] [[認可鯖]]は、[[合言葉]]で[[認証]]する時は、 [[TLS]] を要求しなければ[['''なりません''']]
[SRC[>>201, >>89]]。また[[総当たり攻撃]]に対して[[エンドポイント]]を保護しなければ[['''なりません''']]
[SRC[>>201]]。

[60] [[認可鯖]]は[[基本認証]]以外の[[HTTP認証]]方式に対応しても構いませんが、
[[クライアント識別子]]と当該認証方式との対応関係を定義しなければ[['''なりません''']] 
[SRC[>>201]]。

[90] [[認可鯖]]は、[[Webアプリケーション]]たる[[クライアント]]に関して[[合言葉]]よりも強い[[認証]]手段を検討することが[RUBYB[推奨]@en[encourage]]されています。
[[Webアプリケーション]]は[[合言葉]]その他の [[credentials]] の[[機密]]性を維持しなければ[['''なりません''']]。 [SRC[>>89]]

* 認証方式 [CODE[none]]

[111] [DFN[[CODE@en[[[none]]]]]] は、[[クライアント認証]]なしを表します [SRC[>>109, >>8]]。

* 合言葉に基づく認証方式

[28] [RUBYB[[[合言葉]]]@en[password]]を使う場合、[[基本認証]]を使って構いません。
[[クライアント]]に[[合言葉]]を発行した[[認可鯖]]は、[[基本認証]]に対応しなければ[['''なりません''']]。
[SRC[>>201]]

;; [118] [[Google]] と [[Facebook]] [SRC[>>164]]、 [[GitHub]] [SRC[>>166]]
その他いくつかの[[サービス]] [SRC[>>119, >>133, >>142, >>147, >>159, >>163, >>185]]
は、少なくても[[ドキュメント]]に明記されている範囲では、
[[引数]]を使う方法のみ対応していて、[[基本認証]]には対応していないようです。

;; [130] [[Twitter]] など [SRC[>>129, >>144, >>175, >>181, >>6]] は[[基本認証]]にのみ対応しているようです。

;; [141] [[Spotify]] は[[基本認証]]を原則とし、[[引数]]を使う方法にも対応しています
[SRC[>>140]]。 [[Amazon]] は[[引数]]を使う方法を原則とし、[[基本認証]]にも対応しています
[SRC[>>180]]。

;; [174] [[Bitly]] は[[認可符号]]フローにおいては[[引数]]を使う方法のみ記載し、
[[資源所有者合言葉credentials]]フローにおいては[[基本認証]]のみ記載しています [SRC[>>172]]。
なお [[Bitly]] は[[トークンエンドポイント]]において[[基本認証]]のみ、
または[[基本認証]]と [CODE(URI)@en[[[client_id]]]] および [CODE(URI)@en[[[client_secret]]]]
の指定によって[[アクセストークン]]を取得する独自のフローを実装しており [SRC[>>172]]、
その場合[[基本認証]]は[[資源所有者]]の[[利用者名]]と[[合言葉]]になります。

;; [191] [[Ci]] は [CODE@en[[[grant_type]]=[[password]]]] で[[資源所有者合言葉credentials]]
フローを装っていますが、[[クライアント]]の認証を[[引数]]によって行い、
[[資源所有者]]の認証を[[基本認証]]によって行う [SRC[>>190]] としており、
[[OAuth 2.0]] とは異なっています。

;; [155] [[Salesforce]] は[[引数]]を使う方法と、 [[JWT]] を使う方法に対応しています
[SRC[>>154, >>153]]。

** 認証方式 [CODE[client_secret_basic]]

[29] [[基本認証]]を使う場合、[[利用者名]]は[[クライアント識別子]]を [[UTF-8]] で
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[符号化]]したもの、
[[合言葉]]は[[クライアント]]の[[合言葉]]を [[UTF-8]] で
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[符号化]]したものとします。
[SRC[>>201]] これを [DFN[[CODE@en[[[client_secret_basic]]]]]] と呼びます [SRC[>>109, >>8]]。

;; [30] 入力が名前と値の組でないわけですが、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
版[[パーセント符号化]]を使うという意味だと思われます。

[31] なぜか[[認可鯖]]側の解釈の方法は規定されていません。

;; [32] どの[[文字]]が[[パーセント符号化]]されるのか [[RFC]] および参照先の [[HTML4]]
では曖昧なので、[[鯖]]は一旦[[復号]]してから比較する必要がありそうです。

** 認証方式 [CODE[client_secret_post]]

[33] [[認可鯖]]は、 [[payload body]] に[[引数]]を指定する方式に対応しても構いません。
しかし[[クライアント]]は[[基本認証]]を使えない場合のみこの方法を使う[['''べきです''']]。
[[payload body]] でなく[[要求URL]]中で指定しては[['''なりません''']]。 [SRC[>>201]]
これを [DFN[[CODE@en[[[client_secret_post]]]]]] と呼びます [SRC[>>109, >>8]]。

[59] その場合、[[クライアント]]は [CODE(URI)@en[[[client_id]]]] [[引数]]に[[クライアント識別子]]を、
[CODE(URI)@en[[[client_secret]]]] [[引数]]に[RUBYB[クライアント秘密]@en[client secret]]を指定しなければ[['''なりません''']]。
ただし[[クライアント秘密]]が[[空文字列]]なら、 [CODE(URI)@en[[[client_secret]]]]
[[引数]]は省略できます。 [SRC[>>201]]

;; [57] [CODE(URI)@en[[[client_secret]]]] [[引数]]の構文上の制約により、
この方法を使うなら[[合言葉]]に含められるのは[[印字可能ASCII文字]]に限られます。

* assertion に基づく認証方式

[112] [[OpenID Connect]] は [[JWT]] 形式で [CODE(URI)@en[[[client_assertion]]]]
[[引数]]と [CODE(URI)@en[[[client_assertion_type]]]] [[引数]]を指定する[[クライアント認証]]方式を
[CODE@en[[[client_secret_jwt]]]], [CODE@en[[[private_key_jwt]]]]
の2通り規定しています。

[5] [[RFC 7521]] は [CODE(URI)@en[[[client_assertion]]]]
[[引数]]と [CODE(URI)@en[[[client_assertion_type]]]] [[引数]]と省略可能な
[CODE(URI)@en[[[client_id]]]] [[引数]]を使った [[assertion]]
による[[クライアント認証]]方式 [SRC[>>4]] を規定しています。

* クライアント認証 credentials に関する要件

[81] [[認可鯖]]は、[[ネイティブアプリケーション]]や[[利用者エージェントベースのアプリケーション]]である[[クライアント]]に[[クライアント認証]]用の[[合言葉]]その他の
[[credentials]] を発行しては[['''なりません''']]。ただし[[ネイティブアプリケーション]]を特定の[[装置]]上で動作させたものに対しては[[合言葉]]その他の [[credentials]]
を発行しても構いません。 [SRC[>>89]]

[94] [[認可鯖]]は、推測による攻撃を防がなければ[['''なりません''']]。
生成された[[トークン]]の場合、
攻撃者が推測できる確率は 2[SUP[-128]] [[以下]]で[['''なければならず''']]、
2[SUP[-160]] [[以下]]である[['''べきです''']]。
そうでない[[末端利用者]]が扱う[[credentials]]の場合でも、
何らかの方法で保護しなければ[['''なりません''']]。 [SRC[>>89]]

[91] [[認可鯖]]は、[[クライアント認証]]が不可能な時に、
[[クライアント]]の [[identity]] を[RUBYB[検証]@en[validate]]する他の手段を用いる[['''べき''']]です。
例えば、[[リダイレクトURL]]を登録させたり、[[資源所有者]]に協力させたりできます。
[[認可鯖]]は、性質上[[認証]]できない[[クライアント]]については[[リダイレクトURL]]
の登録を求めなければ[['''なりません''']]。それ以外でも不正な[[クライアント]]から[[資源所有者]]を保護する方策をとる[['''べきです''']]。
[[リダイレクトURL]]が正しいからといって[[クライアント]]の [[identity]]
の検証には不十分ではありますが、 [[credentials]] を不正な[[クライアント]]に渡してしまうことは防止できます。 [SRC[>>89]]

[92] [[認可鯖]]は認証していない[[クライアント]]とのやりとりの[[セキュリティー]]を勘案し、
[[更新トークン]]など他の [[credentials]] を渡さないなど注意しなければなりません [SRC[>>89]]。

;; [44] [[認可鯖]]は[[クライアント認証]]を次の目的で使います [SRC[>>34]]。
[FIG(list)[
- [45] [[更新トークン]]や[[認可符号]]とその発行先の[[クライアント]]との紐付け。
[[認可符号]]を安全でない[[通信路]]で[[リダイレクトエンドポイント]]に送る時や[[リダイレクトURL]]
が完全に登録されていない時には特に重要です。
- [46] [[クライアント]]を無効化したり、[[credentials]] を変更したりして、
[[更新トークン]]が漏洩した時に濫用を防止。[[更新トークン]]をすべて変更するよりはこちらの方が容易です。
- [47] [[credentials]] の定期的な[RUBYB[入れ替え]@en[rotation]]を含む[[認証]]管理で良いとされている慣習の実行。
[[更新トークン]]をすべて入れ替えるのは大変ですが、[[クライアントcredentials]]一式だけならずっと容易です。
]FIG]

;; [93] [[認可エンドポイント]]も参照。

* 実装

[REFS[
- [164] [CITE@ja[Access Tokens]] ([TIME[2015-03-05 18:03:06 +09:00]] 版) <https://developers.facebook.com/docs/facebook-login/access-tokens>
- [119] [CITE@en[Authorization Code Grant Flow]] ([TIME[2015-03-05 10:35:42 +09:00]] 版) <https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx>
- [159] [CITE@en[SurveyMonkey - Guide OAuth]] ([TIME[2015-03-05 17:23:37 +09:00]] 版) <https://developer.surveymonkey.com/mashery/guide_oauth>
- [166] [CITE@en[OAuth | GitHub API]] ([TIME[2015-03-05 18:02:01 +09:00]] 版) <https://developer.github.com/v3/oauth/>
- [129] [CITE[Application-only authentication | Twitter Developers]] ([TIME[2015-03-05 10:58:24 +09:00]] 版) <https://dev.twitter.com/oauth/application-only>
- [133] [CITE[1. OAuth認証 - ヤマレコ Web API]] ([TIME[2015-02-25 16:41:06 +09:00]] 版) <https://sites.google.com/site/apiforyamareco/api/oauth>
- [140] [CITE@en-US[Web API Authorization Guide - Spotify Developer]] ([TIME[2015-03-05 15:59:09 +09:00]] 版) <https://developer.spotify.com/web-api/authorization-guide/>
- [142] [CITE@en[OAuth | Slack]] ([[Slack]] 著, [TIME[2015-03-05 16:04:09 +09:00]] 版) <https://api.slack.com/docs/oauth>
- [144] [CITE@en[OAuth2 · reddit/reddit Wiki]] ([TIME[2015-03-05 16:29:00 +09:00]] 版) <https://github.com/reddit/reddit/wiki/OAuth2#user-content-token-retrieval-code-flow>
- [147] [CITE@ja[• Instagram Developer Documentation]] ([TIME[2015-03-05 16:42:50 +09:00]] 版) <https://instagram.com/developer/authentication/>
- [154] [CITE[Understanding the Web Server OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_web_server_oauth_flow.htm>
- [153] [CITE[Understanding the Username-Password OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_username_password_oauth_flow.htm>
- [163] [CITE@en[Authenticating with OAuth 2.0 | LinkedIn Developer Network]] ([TIME[2015-03-05 17:56:22 +09:00]] 版) <https://developer.linkedin.com/docs/oauth2>
- [172] [CITE[Bitly API Documentation]] ([TIME[2014-11-01 00:33:47 +09:00]] 版) <http://dev.bitly.com/authentication.html>
- [175] [CITE[docomo Developer support API 共通リファレンス 第 2.0.4 版]] ([TIME[2015-03-02 17:25:25 +09:00]] 版) <https://devsite-pro.s3.amazonaws.com/contents_file/API_common_reference_latest.pdf>
- [180] [CITE[Login with Amazon Developer Guide for Websites]] ([TIME[2015-01-20 08:36:09 +09:00]] 版) <https://images-na.ssl-images-amazon.com/images/G/01/lwa/dev/docs/website-developer-guide._TTH_.pdf>
- [181] [CITE[Yahoo OAuth 2.0 Guide - Yahoo Developer Network]] ([TIME[2015-03-06 08:52:24 +09:00]] 版) <https://developer.yahoo.com/oauth2/guide/>
- [185] [CITE@en[Dropbox - Core API - endpoint reference]] ([TIME[2015-03-06 09:07:10 +09:00]] 版) <https://www.dropbox.com/developers/core/docs>
- [190] [CITE[Ci API Reference]] ([TIME[2015-02-26 23:06:44 +09:00]] 版) <http://developers.cimediacloud.com/#using-ci-user-credentials>
- [6] [CITE@en[REST API Reference - PayPal Developer]] ([TIME[2015-07-02 12:54:14 +09:00]] 版) <https://developer.paypal.com/docs/api/>
]REFS]

* 関連

[103] 本項の[[クライアント認証]]は、 [[SSLクライアント認証]]とは関係ありません。

;; [300] 理論上は [[TLSクライアント認証]]を [[OAuth 2.0クライアント認証]]の実現方式として採用することもできますが...