署名

署名方式 (HTTP)

[12] OAuth 1.0 で署名を計算する方式を署名方式 (signature method) といいます。 クライアントは選択した署名方式を oauth_signature_method 引数に、計算した署名を oauth_signature 引数に指定することになっています。鯖は署名を確認し、 正当なクライアントからの認証された要求であるかを調べることになっています。

仕様書

署名

[8] 認証された要求には2組のcredentialsが含まれますが、 鯖が認証を検証して認可されていないアクセスを防ぐために、 クライアントは自身が credentials の正当な所有者であることを示す必要があります。 このために credentials の共有秘密または RSA鍵を使って署名します。 >>7

署名方式

[9] 署名方式 (signature method) には次のものがあります。

[10] OAuth 仕様としてはどの署名方式も必須とはなっていません >>7。

[13] HMAC-SHA1 を使うことが多く、それ以外を使うことはあまりないようです。

[27] Twitter >>26、はてな >>28 など >>29, >>30, >>31, >>34, >>35, >>38, >>41, >>51 は HMAC-SHA1 に対応しています。

[25] Google は HMAC-SHA1 と RSA-SHA1 に対応していました >>24。

[37] Open Bank project は HMAC-SHA1 と HMAC-SHA256 (独自) に対応しています >>36。

[45] Adobe Digital Publishing Suite Folio Producer API は HMAC-SHA256 (独自) に対応しているようです >>44。

[47] VitaDock は HMAC-SHA256 (独自) に対応しています >>46, >>48。

[50] WooCommerce は HMAC-SHA1 と HMAC-SHA256 (独自) に対応しています >>49。

[40] Dropbox は PLAINTEXT に対応しています >>39。 HMAC-SHA1 にも対応していると推測されます。

[43] Evernote は HMAC-SHA1 と PLAINTEXT に対応しています >>42。

[11] 鯖は独自の署名方式を使うことができます >>7。

[33] 新しい署名方式を規定する際は、 oauth_body_hash のハッシュアルゴリズムを規定するべきです >>32。

oauth_signature 引数

[3] 認証された要求の oauth_signature 引数は、署名の計算結果の値を表します。

oauth_signature_method 引数

[2] 認証された要求の oauth_signature_method 引数は、 クライアントが使用する署名方法を表します。

[4] この値が PLAINTEXT であるか否かにより、 oauth_timestamp, oauth_nonce が必要か否かが変わります。

処理

[6] 認証された要求も参照。

実装上の困難

[14] 署名は OAuth 1.0 の中で最も複雑で実装しづらく、嫌われていました。 OAuth 2.0 では TLS を必須とすることで署名を除去しています。

[15] 署名は技術的にはそれほど難解ではなく、特に署名アルゴリズムの実装を既存のライブラリーに委ねている場合には、 クライアントや鯖が自前で行わなければならない処理はほとんどありません。 それでも実装しづらいのは、何重にも符号化を重ねていること、 そのパーセント符号化にバリエーションが多く誤った選択をしても気づきにくいこと、 署名対象となる HTTP要求の各構成部分 (URL の各部や引数) の扱いが既存のライブラリーや WAF 等で様々で、それぞれが独自の符号化や変換、 独自データ構造での保持などを行っていて実際に送信される値を取得するのが難しかったり、 不可能だったりすることなど、様々な罠があります。

[16] 例えば鯖は WAF によって復号された対象URLではなく、 要求対象として指定されたパーセント符号化を保持したURLが必要です。

[18] 例えば逆串の裏側で動作する鯖は、クライアントが指定した元の Host: ヘッダーの値にアクセスできる必要があります。

[17] 例えばクライアントは入力として与えられた対象URL に query が含まれていれば、正しく復号して再度符号化して署名対象としなければなりません。

[20] 例えば鯖が使う WAF によっては multipart/form-data と application/x-www-form-urlencoded の payload body を透過的に扱い、署名の計算に必要な後者で指定された引数のみを取り出すことができないかもしれません。

[21] 例えば鯖が HTTP鯖とアプリケーションサーバー、 その中間で動作するミドルウェアといったソフトウェア部品で構成される場合 (具体的には WSGI や PSGI などの場合) で、ミドルウェアが署名の計算に必要な対象URL や application/x-www-form-urlencoded を破壊的に操作する場合、 アプリケーションサーバーは正しく署名を計算できないかもしれません。 アプリケーションサーバーとミドルウェアの開発者が異なる場合やミドルウェアが条件 (URL のパターンや本番サーバーか開発サーバーの違いなど) 次第で適用されたりされなかったりする場合、 アプリケーションサーバー側の開発者が署名の計算に失敗する理由を特定するのは困難かもしれません。

[19] 署名は要求引数を必要としており、要求URL の一部である URL query や application/x-www-form-urlencoded payload body の生成とも関係しています。そのため、狭義の HTTP要求の生成処理と OAuth 1.0 の処理を完全に分離することが難しく、 HTTP 処理ライブラリーのモジュール化設計に悪い影響を与えています。 これも OAuth 1.0、とりわけその署名が嫌われる一因となります。

[22] 署名が正しく処理されるためには鯖とクライアントの両方がすべての生成過程を正しく実装する必要があり、 通常は互いがどのように署名を計算したかを知ることができません。 このことが署名の実装をより困難にしています。

[23] 例えば鯖が使用している署名計算ルーチンが引数に非ASCII文字が含まれる場合だけ文字コードの扱いに不具合があるとします。 その引数に非ASCII文字が含まれることが滅多になければ、 鯖の開発者はその不具合に気づかないかもしれません。 クライアントが正しく署名を計算していると、当然ながら両者の署名は一致しませんが、 クライアント側の開発者がこの不具合に気づくのは困難です (この例ではクライアント側が非ASCII文字を含めることも滅多にないのでしょうから、クライアント側の利用者からの報告で開発者が問題に気づいても、非ASCII文字が原因と特定することさえ難しいかもしれません)。 鯖の開発者としても、署名の不一致が自身の不具合によるものかクライアントの問題によるものか判断するのは困難です。