ロブ、どこにたどり着いたのかわかりませんが、他の誰かがこの質問に出くわした場合に備えて、私の 2 セントを追加したかったのです。
私は多かれ少なかれ、数か月前に同じ質問をし、「OAuth」について聞いたのは一年の大半でした。保護する必要がある REST API を開発していたので、OAuth について読み始めました...そして、頭の中で目が逆戻りし始めました。
私はおそらく、あなたと同じように、OAuth は紛らわしいゴミであると判断し、それをあきらめるまで、1 日か 2 日、スキミングと読書をしっかりと行いました。
それで、私は一般的に API を保護する方法の調査を開始し、それを行う方法をよりよく理解し始めました。最も一般的な方法は、サーバーがメッセージが途中で改ざんされたかどうかを判断するために使用できるメッセージ全体のチェックサム (あなたとサーバーだけが知っている秘密でエンコードされたもの) と共にリクエストを API に送信することのようです。クライアントから、次のように:
- クライアントは /user.json/123?showFriends=true&showStats=true&checksum=kjDSiuas98SD987ad を送信します
- サーバーはそれをすべて取得し、データベースでユーザー「123」を検索し、彼の秘密鍵をロードしてから、(クライアントが使用したのと同じ方法を使用して) 要求引数を指定して OWN チェックサムを再計算します。
- サーバーが生成したチェックサムとクライアントが送信したチェックサムが一致する場合、リクエストは OK で実行されます。そうでない場合は、改ざんされたと見なされ、拒否されます。
チェックサムは HMAC と呼ばれ、これの良い例が必要な場合は、アマゾン ウェブ サービスが使用するものです (ただし、引数は「チェックサム」ではなく「署名」と呼ばれます)。
したがって、これが機能するための重要なコンポーネントの 1 つは、クライアントとサーバーが同じ方法で HMAC を生成する必要があることです (そうしないと、一致しません)。すべての引数を結合する方法に関する規則が必要です。 . その後、突然、OAuth の「パラメーターの自然なバイト順」のがらくたをすべて理解しました...署名を生成する方法のルールを定義するだけでした。
もう 1 つのポイントは、HMAC 生成に含めるすべてのパラメーターは、要求を送信するときに改ざんできない値であるということです。
したがって、URI ステムを署名としてエンコードするだけの場合は、次のようになります。
- /user.json == askJdla9/kjdas+Askj2l8add
メッセージ内で改ざんできないのは URI だけです。すべての引数は、サーバーが再計算する「チェックサム」値の一部ではないため、改ざんできます。
あるいは、計算に EVERY パラメータを含めたとしても、悪意のある仲介者や盗聴者が API 呼び出しを傍受し、それをサーバーに何度も再送信し続ける「リプレイ攻撃」のリスクは依然としてあります。
HMAC 計算にもタイムスタンプ (常に UTC を使用) を追加することで、これを修正できます。
リマインダー: サーバーは同じ HMAC を計算する必要があるため、シークレット キーを除いて、計算で使用する値を送信する必要があります (OAuth はそれを consumer_secret と呼んでいます)。そのため、タイムスタンプを追加する場合は、リクエストとともにタイムスタンプ パラメータを必ず送信してください。
API をリプレイ攻撃から保護したい場合は、ノンス値を使用できます (これはサーバーが生成し、クライアントに与える 1 回限りの使用値であり、クライアントはそれを HMAC で使用し、リクエストを送り返し、サーバーはそのノンス値を確認してから、DB で「使用済み」としてマークし、別のリクエストで再度使用させないようにします)。
注: 「ノンス」は、「リプレイ攻撃」の問題を解決するための非常に正確な方法です。タイムスタンプは優れていますが、コンピューターは常に同期されたタイムスタンプ値を持っているとは限らないため、サーバー側で許容可能なウィンドウを許可する必要があります。リクエストがどれくらい「古い」か (たとえば、10 分、30 分、1 時間.... Amazon は 15 分を使用) で、リクエストを承認または拒否します。このシナリオでは、API は時間枠全体で技術的に脆弱です。
nonce 値は素晴らしいと思いますが、完全性を維持することが重要な API でのみ使用する必要があります。私のAPIでは必要ありませんでしたが、ユーザーが要求した場合に後で追加するのは簡単です...文字通り、DBに「ノンス」テーブルを追加し、次のような新しいAPIをクライアントに公開する必要があります。
そして、彼らがHMAC計算でそれを私に送り返すとき、DBをチェックして、それが以前に使用されたことがないことを確認し、一度使用されたことを確認する必要があります。私がそれを拒否するのと同じナンス。
概要
とにかく、簡単に言うと、今説明したことは基本的に「2-legged OAuth」として知られているものです。クライアントを承認するために機関 (Twitter、Facebook、Google など) にフローする追加の手順はありません。その手順は削除され、代わりにサーバーは、送信している HMAC が一致する場合にクライアントを暗黙的に信頼します。つまり、クライアントは正しい secret_key を持っており、それを使用してメッセージに署名しているため、サーバーはそれを信頼しています。
オンラインで調べ始めると、これは現在、API メソッドを保護するための推奨される方法のように思われます。Amazon は、HMAC を生成するために全体に署名する前に、パラメーターにわずかに異なる組み合わせ方法を使用することを除いて、ほぼ正確にこの方法を使用します。
興味があれば、私はこの旅と思考プロセス全体を、私が学んでいたときに書きました. それは、このプロセスのガイド付き思考ツアーを提供するのに役立つかもしれません.