[2] [[OAuth 1.0]] では[[プロトコル]]を構成する名前と値の組のことを[DFN[[RUBYB[[[引数]]]@en[parameter]]]]と呼んでいます。

* 仕様書

[REFS[
- [21] [CITE@en[RFC 5849 - The OAuth 1.0 Protocol]] ([TIME[2014-12-28 14:19:21 +09:00]] 版) <http://tools.ietf.org/html/rfc5849#section-2>
- [1] [CITE@en[RFC 5849 - The OAuth 1.0 Protocol]] ([TIME[2014-12-28 14:19:21 +09:00]] 版) <http://tools.ietf.org/html/rfc5849#section-3.4.1.3>
- [20] [CITE@en[RFC 5849 - The OAuth 1.0 Protocol]] ([TIME[2014-12-28 14:19:21 +09:00]] 版) <http://tools.ietf.org/html/rfc5849#section-3.5>
- [53] [CITE@en[RFC 5849 - The OAuth 1.0 Protocol]] ([TIME[2014-12-28 14:19:21 +09:00]] 版) <http://tools.ietf.org/html/rfc5849#section-4.4>
- [56] [CITE[RFC Errata Report]] ([TIME[2015-02-02 15:51:36 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=5849>
- [61] [CITE[OAuth / ProblemReporting]] ([TIME[2015-03-05 14:40:40 +09:00]] 版) <http://wiki.oauth.net/w/page/12238543/ProblemReporting>
]REFS]

* 構文

[3] [[引数]]には、
[FIG(list)[
- [4] [[要求]]の [CODE(HTTP)@en[[[Authorization:]]]] [[ヘッダー]]で使われるもの
- [5] [[要求URL]]の [[URL query]] で使われるもの
- [6] [[要求]]の [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
で使われるもの
- [7] [[応答]]の [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
で使われるもの
]FIG]
... があります。

;; [8] [[OAuth 1.0]] は [CODE(MIME)@en[[[multipart/form-data]]]] その他の
[[MIME型]]は使いません。

* 引数の一覧

[30] 次の[[引数]]があり、 [CODE(HTTP)@en[[[Authorization:]]]]、
[[URL query]]、または [[payload body]] で[[クライアント]]により使われます。
[FIG(short list)[
- [CODE(URI)@en[[[oauth_body_hash]]]]
- [CODE(URI)@en[[[oauth_callback]]]]
- [CODE(URI)@en[[[oauth_verifier]]]]
- [CODE(URI)@en[[[oauth_consumer_key]]]]
- [CODE(URI)@en[[[oauth_token]]]]
- [CODE(URI)@en[[[oauth_signature]]]]
- [CODE(URI)@en[[[oauth_signature_method]]]]
- [CODE(URI)@en[[[oauth_timestamp]]]]
- [CODE(URI)@en[[[oauth_nonce]]]]
- [CODE(URI)@en[[[oauth_scope]]]]
- [CODE(URI)@en[[[oauth_session_handle]]]]
- [CODE(URI)@en[[[oauth_token_attributes]]]]
- [CODE(URI)@en[[[oauth_version]]]]
- [CODE(URI)@en[[[oauth_error_in_response_body]]]]
]FIG]

[31] 次の[[引数]]があり、 [[payload body]] で[[鯖]]により使われます。
[FIG(short list)[
- [CODE(URI)@en[[[oauth_token]]]]
- [CODE(URI)@en[[[oauth_token_secret]]]]
- [CODE(URI)@en[[[oauth_callback_confirmed]]]]
]FIG]

[59] 次の[[引数]]があり、 [CODE(HTTP)@en[[[Authorization:]]]]、[[payload body]]
で[[鯖]]により使われます。
[FIG(short list)[
- [CODE(HTTP)@en[[[oauth_problem]]]]
- [CODE(HTTP)@en[[[oauth_acceptable_versions]]]]
- [CODE(HTTP)@en[[[oauth_acceptable_timestamps]]]]
- [CODE(HTTP)@en[[[oauth_parameters_absent]]]]
- [CODE(HTTP)@en[[[oauth_parameters_rejected]]]]
- [CODE(HTTP)@en[[[oauth_problem_advice]]]]
- [CODE(HTTP)@en[[[oauth_session_handle]]]]
- [CODE(HTTP)@en[[[oauth_authorization_expires_in]]]]
- [CODE(HTTP)@en[[[oauth_expires_in]]]]
]FIG]

[32] 次の[[引数]]があり、[[資源所有者]]にアクセスさせる [[URL]] 
([[コールバックURL]]) の [[query]] または [[payload body]] で指定します。
[FIG(short list)[
- [CODE(URI)@en[[[oauth_token]]]]
- [CODE(URI)@en[[[oauth_verifier]]]]
]FIG]

[60] 次の[[引数]]があり、[[コールバックエンドポイント]]の [[payload body]]
で指定します。
[FIG(short list)[
- [CODE(HTTP)@en[[[oauth_error_code]]]]
- [CODE(HTTP)@en[[[oauth_error_text]]]]
]FIG]

[22] [[一時credentials要求]]、[[資源所有者認可]]、[[トークン要求]]で使う[[エンドポイント]]の
[[URL]] は [[query]] を含んでいても構いませんが、
[CODE[[[oauth_]]]] から始まる[[引数]]を含んでは[['''なりません''']] [SRC[>>21]]。

;; [58] 実際に用いられている [[OAuth]] の拡張や[[鯖]]独自の[[引数]]で [CODE[[[oauth_]]]]
から始まらないものについては、各[[エンドポイント]]の項を参照。

[29] [CODE(HTTP)@en[[[Authorization:]]]] や [CODE(HTTP)@en[[[WWW-Authenticate:]]]]
[[ヘッダー]]では [CODE(HTTP)@en[[[realm]]]] [[引数]]を使うことができます。
これは [[HTTP]] の通常の意味により解釈されるもので、 [[OAuth]]
としての特別な意味は持っていません。

[33] これらの[[引数]]の名前は、大文字と小文字を区別するようです。ただし
[CODE(HTTP)@en[[[Authorization:]]]] や [CODE(HTTP)@en[[[WWW-Authenticate:]]]]
の [CODE(ABNF)@en[[[auth-param]]]] では[[大文字・小文字不区別]]となるので、
注意が必要です。

;; [34] 実装が大文字での指定も正しく扱えるのかは不明です。[[クライアント]]が[[大文字]]混じりの
[CODE(HTTP)@en[[[Authorization:]]]] を生成することは明示的に禁じられていません。
ただし[[署名基底文字列]]では小文字でなければならないと思われます。
[[鯖]]が[[大文字]]混じりの [CODE(HTTP)@en[[[Authorization:]]]]
を受信した時にどう[[署名基底文字列]]を生成するべきなのかは明らかではありません。

* 要求引数

[9] [[認証された要求]]では、次の[[引数]]のことを[RUBYB[[[要求引数]]]@en[request parameter]]
[SRC[>>1]] と呼んでいます。[[要求引数]]は[[署名]]の対象内となります。

[FIG(list)[
= [11] [[要求]]の [CODE(HTTP)@en[[[Authorization:]] [[OAuth]]]] [[ヘッダー]]の
[CODE(HTTP)@en[[[realm]]]] 以外の[[引数]]の名前と値の組
= [12] [[要求]]の [CODE(HTTP)@en[[[Content-Type:]]]] が
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の場合、 [[payload body]]
をそう解釈した時の名前と値の組
= [10] [[要求URL]]の [[query]] を [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
として解釈した時の名前と値の組
]FIG]

[23] [[認証された要求]]では、 [CODE(URI)@en[[[oauth_]]]] から始まる[[引数]]は、
この3つの指定方法 ([DFN[[RUBYB[転送方法]@en[transmission method]]]]) のいずれか一つのみで指定しなければ[['''なりません''']] [SRC[>>20]]。
[CODE(HTTP)@en[[[Authorization:]]]] を使うのが一番好ましく、
[[query]] を使うのが一番好ましくありません [SRC[>>20]]。

;; [24] 将来の拡張により他の方法が用意される可能性もあります [SRC[>>20]]。
(現実には極めて低いでしょうが。。。)

;; [25] [CODE(URI)@en[[[oauth_]]]] [[引数]]をどの方法で転送したとしても、
[[署名基底文字列]]にはすべての方法で指定されたすべての[[引数]]が含まれます。

;; [41] [[クライアント]]がいずれか1つの[[転送方式]]を使うことが要求されていますが、
[[鯖]]が複数の[[転送方式]]で指定された[[要求]]を拒絶することは要求されていないようです。
実際のところ[[引数]]ごとに別の[[転送方法]]を使うクライアントも存在していて、
それを拒絶しない[[鯖]]も存在しているようです。

;; [51] [[一時credentials要求]]や[[トークン要求]]を除き、一般の[[認証された要求]]では [[OAuth]]
で規定されない[[引数]]が [CODE(URI)@en[[[oauth_]]]] で始まることも禁止されているわけではないようです。
しかし >>23 の規定により、 [[OAuth]] の規定に基づき符号化されることが要求されています。
[[OAuth]] で規定されていない[[引数]]が (偶然にも!) [[OAuth]] で規定されている[[引数]]と同じ名前を持つことは、
仕様書の表現上厳密には禁止されていないとも解釈できますが、
そのような[[要求]]は常識的に考えれば禁止されているとみなすべきでしょう
([[検証]]で [CODE(HTTP)[[[401]]]] を返す[['''べき''']]とされています)。
(普通[[仕様書]]の行間を読むべきではありませんが、 [[IETF]]
の仕様書は曖昧なことがよくあるので仕方ありません。)

[66] [[Evernote]] は[[ヘッダー]]または [[URL query]] での指定に対応していると記述されており
[SRC[>>65]]、 [[payload body]] での指定に対応していないと思われます。

[REFS[
- [65] [CITE@en[認証 - Evernote Developers]] ([TIME[2015-03-06 09:30:38 +09:00]] 版) <https://dev.evernote.com/intl/jp/doc/articles/authentication.php>
]REFS]

[13] [[要求引数]]は、[[署名基底文字列]]の一部となります。
その際 [CODE(HTTP)@en[[[oauth_signature]]]] [[引数]]は、
[[署名基底文字列]]には含めては[['''なりません''']] [SRC[>>1]]。
また省略可能な[[引数]]を省略する場合には、
[[署名基底文字列]]に含めては[['''なりません''']] [SRC[>>1]]。

[14] [[署名基底文字列]]の作成時には [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の[[パーセント符号化]]や [CODE(URI)[[[+]]]] は[[復号]]しますが、 
[CODE(HTTP)@en[[[Authorization:]]]] [[ヘッダー]]の[[引数]]はそのまま[[復号]]せずに使います [SRC[>>1]]。

[46] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の復号の方法として
[[HTML 4.0]] (なぜか [[HTML 4.01]] ではありません。) の[[フォームデータ集合]]の構築の項が参照されています [SRC[>>1]] が、
そこでは符号化の方法しか規定されておらず、実際にどう処理するべきなのかは明らかではありません。
[[非ASCII文字]]や[[バイト列]]は符号化の方法すら示していないので、
どのように[[復号]]するのが正しいのかまったく不明です。

[47] 常に [[UTF-8]] を用い、 [[UTF-8]] として解釈できない[[バイト列]]は [[URL query]]
や [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] では使わないことにするのが[[相互運用性]]が高そうですが、
どの[[クライアント]]や[[鯖]]もそれで問題なく動作するのかは定かではありません。

* 問題を表す引数

[62] [[OAuth Problem Reporting Extension]] [SRC[>>61]] 
は問題の発生を[[鯖]]から[[クライアント]]に通知するためのいくつかの[[引数]]を規定しています。

[FIG(middle list)[
- [CODE(HTTP)@en[[[oauth_problem]]]]
- [CODE(HTTP)@en[[[oauth_acceptable_versions]]]]
- [CODE(HTTP)@en[[[oauth_acceptable_timestamps]]]]
- [CODE(HTTP)@en[[[oauth_parameters_absent]]]]
- [CODE(HTTP)@en[[[oauth_parameters_rejected]]]]
- [CODE(HTTP)@en[[[oauth_problem_advice]]]]
]FIG]

[63] [[鯖]]は、任意の[[HTTP応答]]にこれを含めることができます。
[CODE(HTTP)@en[[[WWW-Authenticate:]] [[OAuth]]]] の [CODE(ABNF)@en[[[auth-param]]]]
として指定する[['''べき''']]です。 [[payload body]] にも指定できます。
両方指定する場合は、同一にする[['''べき''']]です。 [SRC[>>61]]

* 要求引数の正規化

[15] [[要求引数]]の[RUBYB[[[正規化]]]@en[normalization]]は、次のように行います [SRC[>>1]]。

[FIG(steps)[
= [16] 各[[引数]]の名前と値をそれぞれ[[OAuth 1.0パーセント符号化]]します。
= [17] [[引数]]を名前の[[昇順]]で[[整列]]します。同名の[[引数]]が複数あれば、
値で[[整列]]します。
= [18] 名前と値を [CODE[[[=]]]] で連結します。
= [19] [[引数]]を [CODE[[[&]]]] で連結します。
]FIG]

[52] この[[正規化]]結果の値は、[[署名基底文字列]]の一部として使われます。

[69] [[要求引数]]は[[クエリー][URL query]]や[[要求本体]]では
[CODE(MIME)@en[application/x-www-form-urlencoded]] で[[符号化]]されますが、
ここでは [[OAuth 1.0パーセント符号化]]されます。両者の結果は微妙に違うので注意が必要です。

[67] [[signature base string]] の計算時に引数は[[パーセント符号化]]してから[[整列]]されますが、
[[整列]]してから[[パーセント符号化]]する実装があり、正しいサーバーとやりとりできなかったりします。 [TIME[2013-09-14T08:14:08.700Z]]

[68] [[Perlモジュール]] [CODE(perl)@en[[[OAuth::Lite]]]] はその扱いがおかしく、
同名の[[引数]]で[[ASCII文字]]のみの値と[[非ASCII文字]] (など[[パーセント符号化]]されるような[[文字]])
の値が混在していると正しく署名を計算できないようです。
[TIME[2016-02-24T02:57:25.400Z]]

[73] 
この辺 [[RFC]] になる前の [[OAuth 1.0a]] 仕様書と [[RFC]]
とで記述が少し変わっていて、古い仕様書では不明瞭なため意図に反した実装があったので
[[RFC]] で明確化されたものだと思われます。

[74] 
正しい仕様に修正しようとしても[[バグ互換性]]のために古い挙動を維持していることもある
[SRC[>>72]] ようで、
不具合が長期間継続して放置されている事例もみられます [SRC[>>71, >>70]]。

[REFS[
- [72] [CITE@en[Query values sort method is RFC5849 invalid by ninjinkun · Pull Request #5 · lyokato/p5-oauth-lite]] ([TIME[2019-03-26 22:51:23 +09:00]]) <https://github.com/lyokato/p5-oauth-lite/pull/5>
- [71] [CITE[はてなブックマークのタグを一括置換するコマンドラインツールを書いた | Web Scratch]]
([[azu]]著, [TIME[2019-03-26 22:48:16 +09:00]])
<https://efcl.info/2019/02/06/hatenabookmark-rename-tags/>

[FIG(quote)[
[FIGCAPTION[
[70] [CITE@ja[【開発者向け情報】はてなブックマーク REST API で特定条件下においてブックマークの追加・更新に失敗する不具合を修正しました - はてなブックマーク開発ブログ]]
([TIME[2019-03-26 22:47:18 +09:00]])
<http://bookmark.hatenastaff.com/entry/2019/03/06/121008>
]FIGCAPTION]

> 本APIへのリクエストの検証のために内部的に利用している、OAuth関連ライブラリの旧バージョンにおける実装が、OAuth 1.0 の仕様を定義した RFC5849 の パラメータ正規化の仕様に厳密には沿っておりませんでした。そのため、APIのパラメータの仕様によっては、リクエストの検証のためにサーバーサイドで生成したoauth_signatureが、クライアントが生成したものと食い違う場合がありました。

]FIG]


]REFS]

* [CODE(HTTP)@en[Authorization: OAuth]] の [CODE(ABNF)@en[auth-param]] による引数の指定

[26] [CODE(HTTP)@en[[[Authorization:]]]] [[ヘッダー]]を使って[[要求引数]]を表す場合や
[CODE(HTTP)@en[[[WWW-Authenticate:]]]] [[ヘッダー]]を使って[[引数]]を表す場合、
その [[HTTP]] [[credentials]] は [[HTTP]] における [CODE(ABNF)@en[[[auth-param]]]]
構文よりも厳しい制限があります。また名前と値は[[OAuth 1.0パーセント符号化]]されます。

;; [CODE(ABNF)@en[[[auth-param]]]] を参照。なおこの制約は [[credentials]]
のみで、 [[challenge]] には適用されないようです。

[27] [CODE(HTTP)@en[[[realm]]]] [[引数]]は [[HTTP]] 仕様に従い指定しても構いませんし、
省略しても構いません [SRC[>>20]]。

;; [28] しかし指定されていないと壊れる実装もあるようです。

;; [CODE(HTTP)@en[[[realm]]]] も参照してください。

[40] [CODE(URI)@en[[[oauth_]]]] [[引数]]を [CODE(HTTP)@en[[[Authorization:]]]]
以外の方法で指定する場合に [CODE(HTTP)@en[[[Authorization:]]]]
[[ヘッダー]]を含めることは禁止されてはいません。 [CODE(URI)@en[[[oauth_]]]]
[[引数]]を複数の方法で指定することは禁止されているので、それ以外の[[引数]]
([CODE(HTTP)@en[[[realm]]]]) しか指定できなくなります。

[48] この方法で指定された[[引数]]を[[鯖]]がどのように処理するべきかについて、
仕様上明記されていません。 [[HTTP]] 仕様に従って処理した後、
[[OAuth 1.0パーセント符号化]]を[[復号]]する必要がありますが
([[auth-param]] 参照)、どのように処理されるか不明なため、
[[記号]]や[[非ASCII文字]]を使うのは避けた方が安全かもしれません。

* payload body による引数の指定

[35] [[payload body]] によって[[引数]]を表す場合、
[CODE(HTTP)@en[[[Content-Type:]]]] [[ヘッダー]]は
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
でなければ[['''なりません''']] [SRC[>>20]]。

;; [36] 仕様上明示されていませんが、 [CODE(MIME)@en[[[charset]]]]
[[引数]]を [CODE(HTTP)@en[[[Content-Type:]]]] [[ヘッダー]]に指定する実装もあるようです
(が意味はありません)。

;; [64] [[OAuth Problem Reporting Extension]] にも適用されるかどうかは仕様上不明瞭ですが、
適用されると解釈するべきでしょう。

[37] [[payload body]] には他の ([[OAuth]] 以外の) [[引数]]を指定しても構いません。
その場合 [[OAuth]] の[[引数]]は最後に置く[['''べきです''']]。 [SRC[>>20]]

[42] [CODE(HTTP)@en[[[Content-Type:]]]] がない場合や他の [[MIME型]]の場合は、
[[payload body]] は [[OAuth]] の[[引数]]とはみなされません。

[43] [[RFC]] は [[payload body]] が [[HTML 4.0]] の
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の符号化方法で符号化されたものでない場合にも[[要求引数]]とはみなさない
[SRC[>>1]] としていますが、実装がそこまで検査しているかは疑問があるところです。
[[HTML 4.0]] は[[非ASCII文字]]の符号化方法を明記していないので、
そのようなデータは合致しないことになってしまいますが、
流石にそれでは実情に合いません。

;; [45] それ以外の、構文的に正しくない [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
がどう処理されるかなどは未知数です。

;; [44] なぜか当時最新の [[HTML 4.01]] ではなく [[HTML 4.0]] が参照されています。

[49] この方法で指定された[[引数]]を[[鯖]]がどう処理するべきかは仕様書には明記されていませんが、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の規定に従うと解釈するのが自然でしょう。

* URL query による引数の指定

[38] [[URL query]] によって[[要求引数]]を表す場合、
他の ([[OAuth]] 以外の) [[引数]]を指定しても構いません。
その場合 [[OAuth]] の[[引数]]は最後に置く[['''べきです''']]。 [SRC[>>20]]

;; [39] [[query]] の他の部分の制約はなく、 
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] になってなくても構わないようです。
(ただし[[署名基底文字列]]の計算時には [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
として解釈されます。)

[50] この方法で指定された[[引数]]を[[鯖]]がどう処理するべきかは仕様書には明記されていません。
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の規定に従い解釈すれば、
適切に処理できます。

* HTTP キャッシュとの関係

[54] [[HTTPキャッシュ]]は [CODE(HTTP)@en[[[Authorization:]]]]
[[ヘッダー]]があると原則として[[キャッシュ不可能]]と判断しますが、
[[URL query]] や [[payload body]] によって[[要求引数]]を指定すると
(他の条件にもよりますが) [[キャッシュ可能]]と判断します。
[CODE(HTTP)@en[[[Cache-Control:]]]] [[ヘッダー]]を適切に設定するなど配慮が必要です
[SRC[>>53]]。

;; [55] [[OAuth]] を実装する[[ライブラリー]]の類は、どのような環境で使われるか事前にわからないので、
[CODE(HTTP)@en[[[Authorization:]] [[OAuth]]]] や [CODE(HTTP)@en[[[Cache-Control:]] [[private]]]]
など適切な[[ヘッダー]]を付与するのを既定の動作とするのが望ましいと思われます。

* 関連

[57] [[引数 (OAuth 2.0)]] は似ていますが、若干違っています。

* メモ
