1. ホーム
  2. security

OAuth2 のリソース所有者パスワード認証のグラントタイプを使用しているときに、クライアントの認証情報を秘密にする方法

2023-09-07 10:58:24

質問

私たちはレストサービスを構築しており、認証にOAauth 2を使用したいと考えています。その際 現在の草案 (5月19日のv2-16)では、以下のように記述されています。 4つの補助金タイプ . これらは認可(アクセストークン)を取得するための仕組みやフローです。

  1. 認可コード
  2. 暗黙の許可
  3. リソース所有者の認証情報
  4. クライアント認証情報

異なる目的を果たすため、これら4つすべてをサポートする必要があるようです。最初の2つ (そしておそらく最後の1つ) は、APIへのアクセスを必要とするサードパーティアプリから使用されます。認証コードは、安全なサーバー上に存在する幸運な Web アプリケーションを認証する標準的な方法であり、一方、暗黙の許可フローは、認証情報を秘密にすることができないクライアント アプリケーション (モバイル/デスクトップ アプリケーション、JavaScript クライアントなど) のための選択となります。

私たち自身は、モバイルデバイスでより良いユーザー体験を提供するために、3番目のメカニズムを使用したいと考えています。ユーザーをウェブブラウザーのログインダイアログなどに連れて行く代わりに、ユーザーは単にアプリケーションでユーザー名とパスワードを直接入力してログインします。 また、Client Credentials グラントタイプを使用して、どのユーザーとも関連付けられていないパブリックデータを閲覧するために使用できるアクセストークンを取得したいと思います。この場合、これは認証というよりも、API キーに似たもので、私たちに登録されたアプリケーションにのみアクセスを与えるために使用し、必要に応じてアクセスを取り消すオプションを提供するものです。

そこで質問です。

  1. さまざまな種類の助成金の目的を正しく理解できたと思いますか?
  2. クライアントのクレデンシャルを秘密にする方法はありますか? 3 番目と 4 番目のケースでは、クライアント ID とクライアントシークレットをクライアントのどこかに持っている必要がありますが、これは良いアイデアとは思えません。
  3. 暗黙のグラント タイプを使用し、クライアント シークレットを公開しない場合でも、別のアプリケーションが同じ認証メカニズムとクライアント ID を使用してあなたのアプリケーションになりすますことを阻止できるでしょうか?

要約すると、クライアント アプリケーションからクライアント クレデンシャルとリソース オーナー クレデンシャル フローを使用できるようにしたい、ということです。これらのフローの両方は、クライアントの秘密を何らかの方法で保存する必要がありますが、クライアントはモバイルまたは JavaScript アプリケーションであるため、これらは簡単に盗まれる可能性があります。

どのように解決するのか?

私も同様の問題に直面しており、また OAuth の比較的新しいユーザーです。Web フローはモバイル プラットフォームで使用するには恐ろしいように思えますし、いったんユーザーがアプリをインストールして、それが私たちの公式アプリであると信頼すれば、ユーザーはユーザー名/パスワードをアプリに直接入力することに安心できるはずです。

問題は、ご指摘のように、私の API サーバーがアプリの client_id を安全に確認する方法がないことです。アプリのコード/パッケージに client_secret を含めると、アプリをインストールした人に公開されるため、client_secret を要求しても、プロセスの安全性は高まりません。したがって、基本的に、他のアプリはclient_idをコピーすることによって、私のアプリになりすますことができます。

それぞれのポイントに直接回答します。

  1. 私は仕様の異なるドラフトを再読して、何かが変更されたかどうかを確認し、リソース所有者のパスワード認証情報のセクションに主に焦点を当てていますが、これらについてあなたが正しいと思います。Client Credentials(4) は、社内またはサード パーティのサービスによって使用される可能性があり、たとえば、分析またはすべてのユーザーにわたる情報を取得する必要がある場合など、単なる公開情報以上のものにアクセスする必要があるかもしれません。

  2. クライアントの機密情報を保持することはできないと思います。

  3. 他の誰かがあなたのクライアント ID を使用することを止めるものはありません。これは私の問題でもあります。いったんコードがサーバーから離れ、アプリとしてインストールされるか、ブラウザで Javascript として実行されると、何かが秘密であると仮定することはできません。

私たちの Web サイトでは、クライアント認証フローであなたが説明したことと同様の問題がありました。私が最終的に行ったことは、認証をサーバー サイドに移動することでした。ユーザーは私たちの Web アプリを使用して認証できますが、私たちの API への OAuth トークンはサーバー側に格納され、ユーザーの Web セッションに関連付けられます。Javascript コードが行うすべての API リクエストは、実際には Web サーバーへの AJAX 呼び出しです。したがって、ブラウザは API で直接認証されるのではなく、認証された Web セッションを持つことになります。

サードパーティアプリについて話していて、この方法を通じて公開データのみを提供しているという点で、クライアント認証の使用ケースは異なるように思われます。しかし、API キーを取得するために無料の登録を必要とするだけなら、誰も本当に API キーを盗みたいと思う理由はわからないでしょう。

各APIキーの使用状況を監視・分析して、不正使用を検知しようとする。その時点で、あるAPIキーを無効にして、正当なユーザーに新しいキーを与えることができる。これは最良の選択肢かもしれませんが、決して安全ではありません。

もしもう少し厳重にロックしたいのであれば、Refresh Tokenのようなスキームを使うこともできますが、実際にどれだけの利益があるかはわかりません。Javascript が公開されている API トークンを 1 日に 1 回失効させ、サードパーティが (秘密の) リフレッシュ トークンを使用してサーバー側で何らかのリフレッシュを行うよう要求すれば、盗まれた API トークンは 1 日以上有効ではありません。そうすれば、盗まれたapiトークンは1日以上使えなくなります。トークンを盗む可能性のある人は、代わりに登録するようになるかもしれません。しかし、他のすべての人にとって苦痛であるため、これが価値があるかどうかはわかりません。