REST認証とAPIキーの公開


93

私はRESTについて読んでいますが、RESTに関する他の多くの質問が他の多くのサイトやブログと同様にあります。私はこの特定の質問が尋ねられるのを見たことがありませんが...何らかの理由で、私はこの概念に心を包むことができません...

RESTful APIを構築していて、それを保護したい場合、私が見た方法の1つはセキュリティトークンを使用することです。他のAPIを使用したときは、トークンと共有シークレットがありました...理にかなっています。私が理解していないことは、残りのサービス操作へのリクエストがJavaScript(XHR / Ajax)を介して行われていること、FireBug(またはブラウザの「ソースの表示」)のような単純なもので誰かがそれを盗聴するのを防ぐことです。 APIキーをコピーしてから、キーとシークレットを使用してそのユーザーになりすましますか?


私が見た方法の1つはセキュリティトークンを使用することですが、実際には多くの方法があります。具体的な例を挙げてください。「REST」と「登録ユーザー専用のJavaScript APIを利用可能にする」(Googleマップを除く)と混同していると思うかもしれません。
PeterMmm

1
ほぼ2年前に尋ねたので、最終的に何を使用しましたか?
Arjan

私は実際には何も使用せず、コンセプトの作成に頭を抱えようとしていました。上記のPeterMmmのコメントはおそらく本当です...まだこれを実装する必要はありませんでしたが、自分で改善したかった...フォローしてくれてありがとう。
tjans 2013年

回答:


22

APIシークレットは明示的に渡されません。シークレットは現在のリクエストのサインを生成するために使用されます。サーバー側では、サーバーは同じプロセスに従ってサインを生成します。2つのサインが一致する場合、リクエストは正常に認証されます。署名はリクエストではなく、シークレットを通じて渡されます。


9
それで、それが渡された兆候だけの場合...それはまだJavaScriptで公開されていません...そのため、API(JavaScriptによって呼び出されます)を介してWebページにちらつき写真を配置し、あなたが私のページにアクセスした場合、 tページにアクセスした人にAPIキーを公開しますか?
tjans 2011年

6
私が正しく質問しているとは思いません...おそらく、そもそも探していたものが見つからなかった理由の一部でしょう。jqueryを使用してajax呼び出しを行うとき、サーバーに渡されるようにajax呼び出しにapiキーを埋め込む必要があります...その時点で、誰かがAPIキーを見ることができます。それが間違っていると理解している場合、クライアントスクリプトに埋め込まれていないAPIキーはどのようにしてリクエストと共に送信されますか?
tjans 2011年

4
結論:openapi / restapiを使用する前に、apikey + apisecretペアが割り当てられ、apikey +記号がサーバーサイドに転送されて、サーバーがリクエストを行っているユーザーを確実に認識します。セキュリティのためにapisecretがサーバーサイドに転送されることはありません。 。
James.Xu 2011年

7
したがって、「現在のリクエストのサインを生成するためにシークレットが使用されている」という@ James.XuのステートメントはFALSEです!クライアントは秘密を知らないので、それを彼に送るのは安全ではないので(そして他にどのようにそれを知るのでしょうか?)技術的には「秘密鍵」である「秘密」はサーバーによってのみ使用されます(なぜならクライアントのサインと比較されるサインを生成することは他の誰にもわかりません。では、質問:どのような種類のデータが、クライアントとサーバー以外に誰も知らない「APIキー」と組み合わされているのでしょうか。記号= api_key +何ですか?
AC、

1
そうです、@ AC。両方のサーバー(ウェブサイトとサードパーティAPI)が同じシークレットを知っている場合でも、ウェブサイトサーバーで署名を計算し、その結果をHTML / JavaScriptに入れ、ブラウザーにAPIに渡すことはできません。そうすることで他のサーバーは最初のWebサーバーからそのHTMLを要求し、応答から署名を取得して、独自のWebサイトのHTMLでそれを使用できます。(上記の投稿は、HTMLの公開APIキーがどのように安全であるかについての質問には答えないと本当に思います。)
Arjan

61

パートナーが登録したドメインでのみ使用できるAPIを公開しています。そのコンテンツは部分的に公開されています(ただし、私たちが知っているドメインでのみ表示されることが望ましい)が、ほとんどの場合はユーザーに対して非公開です。そう:

  • が表示されているかを確認するには、ユーザーがログインしている必要がありますが、これは個別に処理されます。

  • データが表示される場所を決定するは、公開APIキーを使用して、既知のドメインへのアクセスを制限し、何よりもプライベートユーザーデータがCSRFに対して脆弱でないことを確認します。

このAPIキーは確かに誰にでも表示され、他の方法でパートナーを認証することはなく、REFERERは必要ありません。それでも、それは安全です:

  1. 私たちget-csrf-token.js?apiKey=abc123が要求されたとき:

    1. abc123データベースでキーを検索し、そのキーの有効なドメインのリストを取得します。

    2. CSRF検証Cookieを探します。存在しない場合は、安全なランダム値を生成して、HTTPのみのセッションCookieに入れます。Cookieが存在した場合は、既存のランダムな値を取得します。

    3. APIキーからCSRFトークンを作成し、Cookieからランダムな値を作成して署名します。(サーバー上にトークンのリストを保持するのではなく、値に署名します。どちらの値も署名されたトークンで読み取ることができますが、問題ありません。)

    4. キャッシュされないように応答を設定し、Cookieを追加して、次のようなスクリプトを返します。

      var apiConfig = apiConfig || {};
      if(document.domain === 'expected-domain.com' 
            || document.domain === 'www.expected-domain.com') {
      
          apiConfig.csrfToken = 'API key, random value, signature';
      
          // Invoke a callback if the partner wants us to
          if(typeof apiConfig.fnInit !== 'undefined') {
              apiConfig.fnInit();
          }
      } else {
          alert('This site is not authorised for this API key.');
      }

    ノート:

    • 上記はサーバー側のスクリプトがリクエストを偽造することを防ぎませんが、ブラウザからリクエストされた場合にドメインが一致することを保証するだけです。

    • JavaScript同じ生成元ポリシーにより、ブラウザーがXHR(Ajax)を使用してJavaScriptソースをロードして検査できないことが保証されます。代わりに、通常のブラウザーは<script src="https://our-api.com/get-csrf-token.js?apiKey=abc123">(または動的に同等の)を使用してのみそれをロードでき、コードを実行します。もちろん、サーバーはクロスオリジンリソースシェアリングも、生成されたJavaScriptのJSONPもサポートしないでください。

    • ブラウザスクリプトはdocument.domain、上記のスクリプトをロードする前にの値を変更できます。しかし、同一生成元ポリシーは、のみで、ドメインを短縮することができます取り除く書き換えのように、接頭辞subdomain.example.comだけにexample.com、またはmyblog.wordpress.comwordpress.com、あるいは一部のブラウザでbbc.co.ukしますco.uk

    • JavaScriptファイルがサーバー側のスクリプトを使用してフェッチされた場合、サーバーもCookieを取得します。ただし、サードパーティのサーバーは、ユーザーのブラウザにそのCookieをドメインに関連付けることはできません。したがって、サーバー側スクリプトを使用してフェッチされたCSRFトークンと検証Cookieは、ブラウザーではなく、後続のサーバー側呼び出しでのみ使用できます。ただし、このようなサーバー側の呼び出しにはユーザーCookieが含まれないため、パブリックデータのみをフェッチできます。これは、サーバー側のスクリプトがパートナーのWebサイトから直接こすり取ることができる同じデータです。

  2. ユーザーがログインしたら、ユーザーCookieを好きなように設定します。(ユーザーは、JavaScriptが要求される前にすでにログインしている可能性があります。)

  3. サーバーへの後続のすべてのAPI要求(GETおよびJSONP要求を含む)には、CSRFトークン、CSRF検証Cookie、および(ログオンしている場合は)ユーザーCookieを含める必要があります。これでサーバーは、リクエストが信頼できるかどうかを判断できます。

    1. 有効なCSRFトークンの存在により、ブラウザーによってロードされた場合、JavaScriptが予期されたドメインからロードされたことが保証されます。

    2. 検証Cookieのない CSRFトークンの存在は、偽造を示します。

    3. CSRFトークンとCSRF検証Cookieの両方が存在しても、何も保証されません。これは、偽造されたサーバー側の要求か、ブラウザーからの有効な要求のいずれかである可能性があります。(サポートされていないドメインからのブラウザからのリクエストではない可能性があります。)

    4. ユーザーCookieの存在は、ユーザーがログオンしていることを保証しますが、ユーザーが特定のパートナーのメンバーであること、またはユーザーが正しいWebサイトを表示していることを保証しません。

    5. CSRF検証CookieのないユーザーCookieの存在は、偽造を示します。

    6. ユーザーCookieの存在により、現在のリクエストがブラウザを介して行われることが保証されます。(ユーザーが不明なWebサイトに資格情報を入力しないと仮定し、ユーザーが独自の資格情報を使用してサーバー側の要求を行うことを気にしないと想定します。)CSRF検証Cookie もある場合、そのCSRF検証Cookieはまた、ブラウザを使用して受信しました。次に、我々は次の場合に有効な署名でCSRFトークンを持っている、CSRF検証Cookie内の乱数はそのCSRFトークン内の乱数と一致し、そのトークンのJavaScriptも、CSRF Coo​​kieが設定された非常に同じ以前のリクエスト中に受信されたため、ブラウザも使用されました。これはまた、トークンが設定される前に上記のJavaScriptコードが実行されたことを意味し、その時点で、ドメインは指定されたAPIキーに対して有効でした。

      つまり、サーバーは署名済みトークンのAPIキーを安全に使用できるようになります。

    7. いずれかの時点でサーバーが要求を信頼しない場合、403 Forbiddenが返されます。ウィジェットは、ユーザーに警告を表示することでそれに対応できます。

署名付きCSRFトークンと比較するため、CSRF検証Cookieに署名する必要はありません。Cookieに署名しないと、各HTTPリクエストが短くなり、サーバーの検証が少し速くなります。

生成されたCSRFトークンは無期限に有効ですが、検証Cookieとの組み合わせでのみ有効であるため、ブラウザーが閉じられるまで効果的です。

トークンの署名の有効期間を制限できます。ユーザーがログアウトしたときに、OWASPの推奨を満たすために CSRF検証Cookieを削除できます。また、複数のパートナー間でユーザーごとの乱数を共有しないようにするには、APIキーをCookie名に追加します。しかし、それでも、新しいトークンが要求されたときにCSRF検証Cookieを簡単に更新することはできません。ユーザーが複数のウィンドウで同じサイトを閲覧し、単一のCookieを共有している可能性があるためです(更新すると、すべてのウィンドウで更新され、その後他のウィンドウのJavaScriptトークンは、その単一のCookieと一致しなくなります)。

OAuthを使用している人は、JavaScriptのアイデアを得たOAuthとクライアント側ウィジェットも参照してください。以下のためにサーバー側の私たちは、ドメインを制限するために、JavaScriptコードに頼ることができないAPIの使用は、私たちは、秘密鍵の代わりに、パブリックAPIキーを使用しています。


1
CORSを使用する場合、おそらくそれを安全に拡張できます。上記の代わりOPTIONSに、URLに公開APIキーが含まれるプリフライトされたリクエストを処理する場合、サーバーはブラウザーに許可するドメインを通知する(またはリクエストをキャンセルする)場合があります。ただし、一部のリクエストではプリフライトされたリクエストが不要であるか、CORSをまったく使用しないことに注意してください。CORSにはIE8 +が必要です。いくつかのFlashフォールバックがIE7に使用されている場合、おそらくいくつかのダイナミックcrossdomain.xmlが同じことを達成するのに役立ちます。CORS / Flashはまだ試していません。
Arjan

10

この質問には受け入れられた回答がありますが、明確にするために、共有秘密認証は次のように機能します。

  1. クライアントは公開鍵を持っています。これは誰とでも共有でき、問題ではないため、JavaScriptに埋め込むことができます。これは、サーバー上のユーザーを識別するために使用されます。
  2. サーバーには秘密鍵があり、この秘密は保護する必要があります。したがって、共有キー認証では、秘密キーを保護できる必要があります。したがって、秘密を保護するためにサーバーの仲介者が必要なため、別のサービスに直接接続するパブリックJavaScriptクライアントは不可能です。
  3. サーバーは、秘密鍵(秘密鍵はソルトのようなもの)とタイムスタンプを含むアルゴリズムを使用してリクエストに署名し、タイムスタンプを指定してサービスにリクエストを送信します。タイムスタンプは「リプレイ」攻撃を防ぐためのものです。リクエストの署名は約nに対してのみ有効です秒間。署名に含まれていたタイムスタンプの値が含まれるはずのタイムスタンプヘッダーを取得することで、サーバー上でそれを確認できます。そのタイムスタンプが期限切れの場合、リクエストは失敗します。
  4. サービスは、署名だけでなく、プレーンテキストで署名されたすべてのフィールドを含むリクエストを取得します。
  5. 次に、サービスは共有秘密鍵を使用して同じ方法でリクエストに署名し、署名を比較します。

真実ですが、設計上、あなたの答えはAPIキーを公開していませ。ただし、一部のAPIでは、APIキー公開されており、それが「Javascript(XHR / Ajax)を介して行われたRESTサービス操作へのリクエスト[...]」に関する質問でした。(それについても受け入れられた答えは間違っていると思います。あなたのポイント2はそれについて明確です。良いことです。)
Arjan

1

私はあなたがAPIキーではなくセッションキーを意味していると思います。この問題はhttpプロトコルから継承され、セッションハイジャックとして知られています。通常の「回避策」は、他のWebサイトと同様に、httpsに変更することです。

RESTサービスを安全に実行するには、httpsと、おそらくクライアント認証を有効にする必要があります。しかし結局のところ、これはRESTの考えを超えています。RESTはセキュリティについて決して話しません。


8
私は実際にキーを意味しました。私の記憶が正しければ、APIを使用するために、APIキーとシークレットを残りのサービスに渡して認証しますよね?回線を通過するとSSLで暗号化されますが、送信される前に、それを使用するクライアントコードで完全に表示されます...
tjans

1

サーバー側で実行したいことは、ログインまたはサインアップ時にクライアントに送り返される期限切れのセッションIDを生成することです。クライアントは、そのセッションIDを共有シークレットとして使用して、後続のリクエストに署名できます。

セッションIDは1回だけ渡され、これはSSL経由である必要があります。

こちらの例をご覧ください

セッションのハイジャックを防ぐために、リクエストに署名するときはナンスとタイムスタンプを使用します。


1
しかし、サードパーティがあなたのAPIを使用している場合どのようにログインすることができますか?場合は、ユーザーがログインしようとしている、そして物事は簡単です:ちょうどセッションを使うのか?しかし、他のWebサイトがAPIに対して認証する必要がある場合、それは役に立ちません。(また、これはあなたのブログを宣伝するようなもののにおいがします。)
Arjan

1

元の文脈で質問に答えてみます。したがって、質問は「秘密(API)キーはJavaScriptで安全に配置できるかどうかです。

私の意見では、システム間の認証の目的に反するため、非常に危険です。キーはユーザーに公開されるため、ユーザーは許可されていない情報を取得する可能性があります。なぜなら、通常の残りの通信では、認証はAPIキーのみに基づいているからです。

私の見解では、JavaScript呼び出しは本質的にはREST呼び出しの作成を担当する内部サーバーコンポーネントにリクエストを渡すというものです。内部サーバーコンポーネントが、サーブレットが許可ベースのファイルシステムなどの保護されたソースからAPIキーを読み取り、HTTPヘッダーに挿入して外部REST呼び出しを行うとしましょう。

これがお役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.