web-dev-qa-db-ja.com

「暗黙的」フローが非常にうまく機能するのに、なぜOAuth2に「認証コード」フローがあるのですか?

「暗黙的」フローでは、リソース所有者(つまりユーザー)がアクセスを許可した後、クライアント(おそらくブラウザ)がアクセストークンを取得します。

ただし、「承認コード」フローでは、クライアント(通常はWebサーバー)は、リソース所有者(つまりユーザー)がアクセスを許可した後にのみ承認コードを取得します。その認証コードを使用して、クライアントは、アクセスコードを取得するための認証コードとともにclient_idとclient_secretを渡すAPIを再度呼び出します。 ここですべて説明

両方のフローの結果は、アクセストークンとまったく同じです。ただし、「暗黙的」フローははるかに単純です。

質問:「暗黙の」フローの継ぎ目がうまくいくのに、なぜ「認証コード」のフローに悩まされるのですか? Webサーバーに「暗黙」も使用しないのはなぜですか?

プロバイダーとクライアントの両方にとってより多くの作業が必要です。

225
Aron Woost

tl; dr:これはすべてセキュリティ上の理由によるものです。

OAuth 2.0は、次の2つの基準を満たすことを望んでいました。

  1. すべての開発者がSSL対応のサーバーを持っているわけではないため、開発者が非HTTPSリダイレクトURIを使用できるようにしたいと考えています。
  2. ハッカーがリクエストを傍受してアクセス/更新トークンを盗むことを望まない。

以下の詳細:

暗黙的なフローは、セキュリティ上の理由により、ブラウザー環境でのみ可能です。

暗黙のフローでは、アクセストークンは(URLパラメーターとしてではなく)ハッシュフラグメントとして直接渡されます。ハッシュフラグメントに関する重要な点の1つは、ハッシュフラグメントを含むリンクをたどると、ブラウザのみがハッシュフラグメントを認識していることです。ブラウザは、ハッシュフラグメントを宛先Webページ(リダイレクトURI /クライアントのWebページ)に直接渡します。ハッシュフラグメントには次のプロパティがあります。

  • これらはHTTPリクエストの一部ではないため、サーバーで読み取ることはできません。そのため、中間サーバー/ルーターでインターセプトできません(これは重要です)。
  • これらはブラウザ(クライアント側)にのみ存在するため、ハッシュフラグメントを読み取る唯一の方法は、ページで実行されるJavaScriptを使用することです。

これにより、中間サーバーによってインターセプトされるリスクなしに、アクセストークンをクライアントに直接渡すことができます。これには、可能なクライアント側のみであるという警告があり、アクセストークンを使用するには、クライアント側でJavaScriptを実行する必要があります。

認証コードフローでは、URLパラメーターはHTTP要求の一部であるため、URLパラメーターでアクセストークンを直接渡すことはできません。したがって、要求が通過する中間サーバー/ルーター暗号化接続(HTTPS)を使用していない場合、アクセストークンを読み取って、中間者攻撃と呼ばれるものを許可できる可能性があります。

アクセストークンをURLパラメーターで直接渡すことは理論的には可能ですが、認証サーバーはリダイレクトURIがTLS暗号化と「信頼された」SSL証明書(通常は無料ではない認証局から)を備えたHTTPSを使用していることを確認する必要があります宛先サーバーが正当であり、HTTP要求が完全に暗号化されていることを確認してください。すべての開発者がSSL証明書を購入し、ドメインでSSLを適切に構成するのは大きな苦痛であり、採用が大幅に遅くなります。これが、正当な受信者のみが(クライアントシークレットが必要なため)交換でき、暗号化されていないトランザクションを介してリクエストを傍受する潜在的なハッカーにとってコードが役に立たないという、1回限りの「承認コード」が提供される理由です(クライアントの秘密がわからないため)。

また、暗黙的なフローは安全性が低いと主張することもできます。たとえば、クライアントのWebサイトのIPアドレスをハイジャックすることにより、リダイレクト時にドメインをスプーフィングするなどの潜在的な攻撃ベクトルがあります。これは、暗黙のフローがアクセストークン(時間の使用が制限されていると想定される)のみを許可し、トークンを更新しない(時間に制限がない)理由の1つです。この問題を解決するには、可能な限りHTTPS対応サーバーでWebページをホストすることをお勧めします。

253
Nicolas Garnier

Implicit Flowはフロー全体をかなり簡単にしますが、安全性も低下します
通常、ブラウザ内で実行されるJavaScriptであるクライアントアプリケーションは信頼性が低いため、長期間アクセスするための更新トークンは返されません。
このフローは、ユーザーのデータへの一時的なアクセス(数時間)が必要なアプリケーションに使用する必要があります。

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

8
lakesare

OAuth仕様 から:

4.2。暗黙のグラント

暗黙的な許可タイプはアクセストークンの取得に使用され(リフレッシュトークンの発行をサポートしません)、特定のリダイレクトURIを操作することが知られているパブリッククライアント向けに最適化されています。これらのクライアントは、通常、JavaScriptなどのスクリプト言語を使用してブラウザーに実装されます。

これはリダイレクトベースのフローであるため、クライアントはリソース所有者のユーザーエージェント(通常はWebブラウザー)と対話でき、承認サーバーから着信要求を(リダイレクト経由で)受信できる必要があります。

クライアントが承認とアクセストークンに対して別々のリクエストを行う承認コード付与タイプとは異なり、クライアントは承認リクエストの結果としてアクセストークンを受け取ります。

暗黙的な許可タイプにはクライアント認証は含まれず、リソース所有者の存在とリダイレクトURIの登録に依存します。アクセストークンはリダイレクトURIにエンコードされているため、リソース所有者と同じデバイス上にある他のアプリケーションに公開される場合があります。

考慮できること:

  1. これは、パブリックOAuth用です。つまり、クライアントを登録する必要がなく、独自のクライアントシークレットがない場合です。しかし、認証サーバーがリダイレクトURLをチェックするものであり、これは実際にはセキュリティに十分です。

  2. アクセストークンはブラウザのアドレスバーに表示されるため、ユーザーはURLをコピーして他の人に送信できます。また、ユーザーとしてログに記録されるようになります。しかし、ブラウザーは、URLからハッシュフラグメントを削除するために、履歴を置き換える追加のリダイレクトを行います。ハッカーがHTTPトラフィックを盗聴してアクセストークンを盗むことも可能ですが、これはHTTPSで簡単に保護できます。悪意のあるブラウザ拡張機能の中には、アドレスバーからURLにアクセスできるものもありますが、これは最終的にHTTPS証明書が壊れているような悪い状況です。そして、認証コードフローでさえ、ここでは役に立ちません。したがって、URLのハッシュフラグメントを介してアクセストークンを渡すことは絶対に安全です。

  3. 一時アクセストークンとリフレッシュトークンの分離は、HTTPSを使用する場合は無意味であり、正直なところ、生のHTTPでもそれほど有用ではありません。しかし、暗黙的なフローを介したクライアントが更新トークンを受信できないという事実もナンセンスです。

したがって、httpsで厳密に動作し、更新トークンを許可する(またはそれらを完全に削除する必要がある)Auth Cose許可フローよりも望ましい新しい許可フロー「safe implicit」を導入する必要があると思います

2
stokito

私の答えは、Webアプリサーバーでは暗黙的フローを安全かつ簡単な方法で実装することはできません。

Webアプリの承認プロセスにはユーザーインタラクションが含まれるため、認証サーバーはユーザー認証と同意後にリダイレクトユーザーのブラウザーをWebアプリのターゲットページに戻す必要があります(ユーザーを他の方法に戻す方法はありません)認証サーバーとの対話後のwebアプリ)。

トークンはリダイレクトURLを使用してwebアプリに渡す必要がありますか?

@NicolasGarnierが回答とコメントで説明したように、トークンをURLフラグメントとして渡す方法はありません。Webアプリケーションサーバーに到達しません。

また、リダイレクトURLのURLパラメーターとしてトークンを渡すことはHTTPSでも安全ではありません。ターゲットページ(「グリーティングページ」とする)にリソース(画像、スクリプトなど)が含まれている場合、このリソースはシリーズを通じてブラウザーによって取得されますHTTP(S)リクエスト(それぞれがReferer HTTPヘッダーを持ち、URLパラメーターを含む「挨拶ページ」の正確なURLを含む)。これは、トークンがリークする可能性がある方法です。

そのため、リダイレクトURLにトークンを渡す方法はないようです。そのため、2番目の呼び出し(認証サーバーからクライアントへ(ただし、どのURLへ?)またはクライアントから認証サーバーへ(承認コードフローの2番目の呼び出し))が必要です。

0
Lu55