[12] [[OAuth 1.0]] で[[署名]]を計算する方式を[DFN[[RUBYB[署名方式]@en[signature method]]]]といいます。
[[クライアント]]は選択した[[署名方式]]を [DFN[[CODE(URI)@en[[[oauth_signature_method]]]]]]
[[引数]]に、計算した[[署名]]を [DFN[[CODE(URI)@en[[[oauth_signature]]]]]]
[[引数]]に指定することになっています。[[鯖]]は[[署名]]を確認し、
正当な[[クライアント]]からの[[認証された要求]]であるかを調べることになっています。

* 仕様書

[REFS[
- [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.1>
- [5] [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.2>
- [7] '''[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>'''
- [32] [CITE@en[Final: OAuth Request Body Hash]] ([TIME[2009-04-12 08:08:27 +09:00]] 版) <http://oauth.googlecode.com/svn&l=52/spec/ext/body_hash/1.0/oauth-bodyhash.html#anchor3>
]REFS]

* 署名

[8] [[認証された要求]]には2組の[[credentials]]が含まれますが、
[[鯖]]が[[認証]]を[[検証]]して[[認可]]されていないアクセスを防ぐために、
[[クライアント]]は自身が [[credentials]] の正当な所有者であることを示す必要があります。
このために [[credentials]] の[[共有秘密]]または [[RSA鍵]]を使って[[署名]]します。 [SRC[>>7]]

* 署名方式

[9] [RUBYB[署名方式]@en[signature method]]には次のものがあります。
[FIG(short list)[
- [CODE(HTTP)@en[[[HMAC-SHA1]]]]
- [CODE(HTTP)@en[[[HMAC-SHA256]]]]
- [CODE(HTTP)@en[[[RSA-SHA1]]]]
- [CODE(HTTP)@en[[[PLAINTEXT]]]]
]FIG]

[10] [[OAuth]] 仕様としてはどの[[署名方式]]も必須とはなっていません [SRC[>>7]]。

;; [13] [CODE(HTTP)@en[[[HMAC-SHA1]]]] を使うことが多く、それ以外を使うことはあまりないようです。

[27] [[Twitter]] [SRC[>>26]]、[[はてな]] [SRC[>>28]] など [SRC[>>29, >>30, >>31, >>34, >>35, >>38, >>41, >>51]] は [CODE(HTTP)@en[[[HMAC-SHA1]]]]
に対応しています。

[25] [[Google]] は [CODE(HTTP)@en[[[HMAC-SHA1]]]] と [CODE(HTTP)@en[[[RSA-SHA1]]]]
に対応していました [SRC[>>24]]。

[37] [[Open Bank project]] は [CODE(HTTP)@en[[[HMAC-SHA1]]]] と
[CODE(HTTP)@en[[[HMAC-SHA256]]]] (独自) に対応しています [SRC[>>36]]。

[45] [[Adobe Digital Publishing Suite]] [[Folio Producer]] API は
[CODE(HTTP)@en[[[HMAC-SHA256]]]] (独自) に対応しているようです [SRC[>>44]]。

[47] [[VitaDock]] は [CODE(HTTP)@en[[[HMAC-SHA256]]]] (独自) に対応しています [SRC[>>46, >>48]]。

[50] [[WooCommerce]] は [CODE(HTTP)@en[[[HMAC-SHA1]]]] と [CODE(HTTP)@en[[[HMAC-SHA256]]]]
(独自) に対応しています [SRC[>>49]]。

[40] [[Dropbox]] は [CODE(HTTP)@en[[[PLAINTEXT]]]] に対応しています [SRC[>>39]]。
[CODE(HTTP)@en[[[HMAC-SHA1]]]] にも対応していると推測されます。

[43] [[Evernote]] は [CODE(HTTP)@en[[[HMAC-SHA1]]]] と [CODE(HTTP)@en[[[PLAINTEXT]]]]
に対応しています [SRC[>>42]]。

[REFS[
- [26] [CITE[Authorizing a request | Twitter Developers]] ([TIME[2015-03-05 11:17:28 +09:00]] 版) <https://dev.twitter.com/oauth/overview/authorizing-requests>
- [28] [CITE[OAuth 認証時のエラー一覧 - Hatena Developer Center]] ([TIME[2015-03-05 15:25:33 +09:00]] 版) <http://developer.hatena.ne.jp/ja/documents/auth/apis/oauth/problems>
- [24] [CITE@ja[OAuth 1.0 API Reference - Google Accounts Authentication and Authorization — Google Developers]] ([TIME[2014-12-05 11:52:26 +09:00]] 版) <https://developers.google.com/accounts/docs/OAuth_ref#SigningOAuth>
- [29] [CITE[OpenPNE3 OAuth 対応アプリケーション作成ガイド]] ([TIME[2009-09-11 15:26:43 +09:00]] 版) <https://trac.openpne.jp/svn/OpenPNE3/doc/branches/develop/OAuth/ja.txt>
- [30] [CITE[apiDoc: Withings - 1.0.0]] ([TIME[2015-03-05 16:20:37 +09:00]] 版) <http://oauth.withings.com/api/doc#api-OAuth_Authentication>
- [31] [CITE[OAuth on Bitbucket - Bitbucket - Atlassian Documentation]] ([TIME[2015-03-05 18:51:40 +09:00]] 版) <https://confluence.atlassian.com/display/BITBUCKET/OAuth+on+Bitbucket>
- [34] [CITE[OAuth Authentication in the Fitbit API - API - Confluence]] ([TIME[2015-03-06 08:29:40 +09:00]] 版) <https://wiki.fitbit.com/display/API/OAuth+Authentication+in+the+Fitbit+API>
- [35] [CITE[Consumer Authentication]] ([TIME[2012-09-26 04:52:48 +09:00]] 版) <http://pic.photobucket.com/dev_help/WebHelpPublic/Content/Getting%20Started/Consumer%20Authentication.htm>
- [36] [CITE@en[OAuth 1.0 Server · OpenBankProject/OBP-API Wiki]] ([TIME[2015-03-06 08:46:04 +09:00]] 版) <https://github.com/OpenBankProject/OBP-API/wiki/OAuth-1.0-Server>
- [38] [CITE[AWeber Email Marketing API - API Reference - OAuth Authentication]] ([TIME[2015-03-06 08:57:06 +09:00]] 版) <https://labs.aweber.com/docs/authentication>
- [39] [CITE@en[Using OAuth 1.0 with the “PLAINTEXT” signature method | Dropbox Developer Blog]] ([TIME[2015-03-06 09:25:13 +09:00]] 版) <https://blogs.dropbox.com/developers/2012/07/using-oauth-1-0-with-the-plaintext-signature-method/>
- [41] [CITE@ja[API | Tumblr]] ([TIME[2015-03-06 09:27:33 +09:00]] 版) <https://www.tumblr.com/docs/en/api/v2>
- [42] [CITE@en[認証 - Evernote Developers]] ([TIME[2015-03-06 09:30:38 +09:00]] 版) <https://dev.evernote.com/intl/jp/doc/articles/authentication.php>
- [44] [CITE@en[folio-producer-api/CreateSession.php at 3bd6b18ec96fd26eb53ff3833d1b2d2aa434b3f8 · CoffeeAndCode/folio-producer-api]] ([TIME[2015-03-13 09:20:25 +09:00]] 版) <https://github.com/CoffeeAndCode/folio-producer-api/blob/3bd6b18ec96fd26eb53ff3833d1b2d2aa434b3f8/app/DPSFolioProducer/Commands/CreateSession.php#L73>
- [46] [CITE@en[AUTHORIZATION Header · Medisana/vitadock-api Wiki]] ([TIME[2015-03-13 09:35:48 +09:00]] 版) <https://github.com/Medisana/vitadock-api/wiki/AUTHORIZATION-Header#user-content-signature>
- [48] [CITE@en[Definitions · Medisana/vitadock-api Wiki]] ([TIME[2015-03-13 09:37:46 +09:00]] 版) <https://github.com/Medisana/vitadock-api/wiki/Definitions>
- [49] [CITE[WooCommerce REST API Documentation v2]] ([TIME[2015-03-11 03:10:19 +09:00]] 版) <http://woothemes.github.io/woocommerce-rest-api-docs/#authentication>
- [51] [CITE@en[Opera: Opera Link API Beta]] ([[Frank M. Palinkas, Technical Writer]] 著, [TIME[2015-03-14 20:58:39 +09:00]] 版) <http://www.opera.com/docs/apis/linkrest/#auth>
]REFS]

[11] [[鯖]]は独自の[[署名方式]]を使うことができます [SRC[>>7]]。

[33] 新しい[[署名方式]]を規定する際は、 [CODE(URI)@en[[[oauth_body_hash]]]]
の[[ハッシュアルゴリズム]]を規定する[['''べきです''']] [SRC[>>32]]。

* [CODE(URI)@en[oauth_signature]] 引数

[3] [[認証された要求]]の [DFN[[CODE(URI)@en[[[oauth_signature]]]]]]
[[引数]]は、[[署名]]の計算結果の値を表します。

* [CODE(URI)@en[oauth_signature_method]] 引数

[2] [[認証された要求]]の [DFN[[CODE(URI)@en[[[oauth_signature_method]]]]]] [[引数]]は、
[[クライアント]]が使用する[[署名方法]]を表します。

[4] この値が [CODE(HTTP)@en[[[PLAINTEXT]]]] であるか否かにより、
[CODE(HTTP)@en[[[oauth_timestamp]]]], [CODE(HTTP)@en[[[oauth_nonce]]]]
が必要か否かが変わります。

* 処理

[6] [[認証された要求]]も参照。

* 実装上の困難

[14] [[署名]]は [[OAuth 1.0]] の中で最も複雑で実装しづらく、嫌われていました。
[[OAuth 2.0]] では [[TLS]] を必須とすることで[[署名]]を除去しています。

[15] [[署名]]は技術的にはそれほど難解ではなく、特に[[署名アルゴリズム]]の実装を既存のライブラリーに委ねている場合には、
[[クライアント]]や[[鯖]]が自前で行わなければならない処理はほとんどありません。
それでも実装しづらいのは、何重にも[[符号化]]を重ねていること、
その[[パーセント符号化]]にバリエーションが多く誤った選択をしても気づきにくいこと、
[[署名]]対象となる [[HTTP要求]]の各構成部分 ([[URL]] の各部や[[引数]])
の扱いが既存のライブラリーや [[WAF]] 等で様々で、それぞれが独自の[[符号化]]や変換、
独自データ構造での保持などを行っていて実際に送信される値を取得するのが難しかったり、
不可能だったりすることなど、様々な罠があります。

[EG[
[16] 例えば[[鯖]]は [[WAF]] によって[[復号]]された[[対象URL]]ではなく、
[[要求対象]]として指定された[[パーセント符号化]]を保持した[[URL]]が必要です。
]EG]

[EG[
[18] 例えば[[逆串]]の裏側で動作する[[鯖]]は、[[クライアント]]が指定した元の
[CODE(HTTP)@en[[[Host:]]]] [[ヘッダー]]の値にアクセスできる必要があります。
]EG]

[EG[
[17] 例えば[[クライアント]]は入力として与えられた[[対象URL]]
に [[query]] が含まれていれば、正しく[[復号]]して再度[[符号化]]して[[署名]]対象としなければなりません。
]EG]

[EG[
[20] 例えば[[鯖]]が使う [[WAF]] によっては [CODE(MIME)@en[[[multipart/form-data]]]] と
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の [[payload body]]
を透過的に扱い、[[署名]]の計算に必要な後者で指定された[[引数]]のみを取り出すことができないかもしれません。
]EG]

[EG[
[21] 例えば[[鯖]]が [[HTTP鯖]]と[[アプリケーションサーバー]]、
その中間で動作する[[ミドルウェア]]といったソフトウェア部品で構成される場合
(具体的には [[WSGI]] や [[PSGI]] などの場合) で、[[ミドルウェア]]が[[署名]]の計算に必要な[[対象URL]]
や [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] を破壊的に操作する場合、
[[アプリケーションサーバー]]は正しく[[署名]]を計算できないかもしれません。
[[アプリケーションサーバー]]と[[ミドルウェア]]の開発者が異なる場合や[[ミドルウェア]]が条件
([[URL]] のパターンや本番サーバーか開発サーバーの違いなど) 次第で適用されたりされなかったりする場合、
[[アプリケーションサーバー]]側の開発者が[[署名]]の計算に失敗する理由を特定するのは困難かもしれません。
]EG]

[19] [[署名]]は[[要求引数]]を必要としており、[[要求URL]] の一部である [[URL query]] や
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
の生成とも関係しています。そのため、狭義の [[HTTP要求]]の生成処理と [[OAuth 1.0]]
の処理を完全に分離することが難しく、 [[HTTP]] 処理ライブラリーのモジュール化設計に悪い影響を与えています。
これも [[OAuth 1.0]]、とりわけその[[署名]]が嫌われる一因となります。

[22] [[署名]]が正しく処理されるためには[[鯖]]と[[クライアント]]の両方がすべての生成過程を正しく実装する必要があり、
通常は互いがどのように[[署名]]を計算したかを知ることができません。
このことが[[署名]]の実装をより困難にしています。

[EG[
[23] 例えば[[鯖]]が使用している[[署名]]計算ルーチンが[[引数]]に[[非ASCII文字]]が含まれる場合だけ[[文字コード]]の扱いに不具合があるとします。
その[[引数]]に[[非ASCII文字]]が含まれることが滅多になければ、
[[鯖]]の開発者はその不具合に気づかないかもしれません。
[[クライアント]]が正しく[[署名]]を計算していると、当然ながら両者の[[署名]]は一致しませんが、
[[クライアント]]側の開発者がこの不具合に気づくのは困難です (この例では[[クライアント]]側が[[非ASCII文字]]を含めることも滅多にないのでしょうから、[[クライアント]]側の[[利用者]]からの報告で開発者が問題に気づいても、[[非ASCII文字]]が原因と特定することさえ難しいかもしれません)。
[[鯖]]の開発者としても、[[署名]]の不一致が自身の不具合によるものか[[クライアント]]の問題によるものか判断するのは困難です。
]EG]