web-dev-qa-db-ja.com

OAuth 2.0:利点とユースケース—なぜですか?

誰もがOAuth2の長所とそれを実装する理由を説明できますか?私はそれについて少し混乱しているので尋ねます-私の現在の考えはここにあります:

OAuth1(より正確にはHMAC)リクエストは、論理的で、理解しやすく、開発しやすく、本当に安全だと思われます。

代わりに、OAuth2は承認リクエスト、アクセストークン、およびリフレッシュトークンをもたらします。セッションの開始時に3つのリクエストを行って、必要なデータを取得する必要があります。その場合でも、トークンの有効期限が切れると、リクエストのいずれかが最終的に失敗します。

また、別のアクセストークンを取得するには、アクセストークンと同時に渡された更新トークンを使用します。それはセキュリティの観点からアクセストークンを無駄にしますか?

さらに、/ r/netsecが最近示したように、SSLは完全に安全ではないため、安全なHMACではなくTLS/SSLにすべてをプッシュすることは私を混乱させます。

OAuthは、100%の安全性ではないと主張していますが、公開して完成させています。それは、プロバイダーの観点からは、必ずしも有望ではありません。ドラフトが6つの異なるフローに言及しているときに達成しようとしているものを見ることができますが、それは私の頭に収まりきっていません。

実際にそれを嫌うよりも、その利点と推論を理解するのが私の苦労だと思うので、これはちょっとした不当な攻撃かもしれません。

241
tonyhb

背景:OAuth 1.0aおよび2.0のクライアントおよびサーバースタックを作成しました。

OAuth 1.0aおよび2.0の両方が、サーバーがユーザーのIDを保証するtwo-legged authenticationと、three-legged authenticationをサポートします。サーバーは、ユーザーの身元がコンテンツプロバイダーによって保証されています。スリーレッグ認証は、認可リクエストとアクセストークンが作用する場所であり、OAuth 1にもそれらがあることに注意することが重要です。

複雑なもの:三本足認証

OAuth仕様の主なポイントは、コンテンツプロバイダー(例:Facebook、Twitterなど)がサーバー(例:Webアプリクライアントに代わってコンテンツプロバイダーと会話したい場合)、クライアントに何らかの識別情報があることを確認します。スリーレッグ認証が提供するのは、クライアントまたはサーバーがそのIDの詳細を知る必要なしにそれを行う機能です(例:ユーザー名とパスワード)。

OAuthの詳細に深く入り込むことなく(?):

  1. クライアントはサーバーに認証要求を送信し、サーバーがクライアントがそのサービスの正当なクライアントであることを検証します。
  2. サーバーは、クライアントをコンテンツプロバイダーにリダイレクトして、そのリソースへのアクセスを要求します。
  3. コンテンツプロバイダーはユーザーのIDを検証し、多くの場合、リソースへのアクセス許可を要求します。
  4. コンテンツプロバイダーはクライアントをサーバーにリダイレクトし、成功または失敗を通知します。このリクエストには、成功時の認証コードが含まれます。
  5. サーバーは、コンテンツプロバイダーに帯域外要求を行い、アクセストークンの認証コードを交換します。

これで、サーバーは、アクセストークンを渡すことにより、ユーザーに代わってコンテンツプロバイダーに要求を行うことができます。

各交換(クライアント->サーバー、サーバー->コンテンツプロバイダー)には共有シークレットの検証が含まれますが、OAuth 1は暗号化されていない接続で実行できるため、各検証はワイヤー経由でシークレットを渡すことができません。

既に述べたように、これはHMACで行われました。クライアントは、サーバーと共有するシークレットを使用して、承認要求の引数に署名します。サーバーは引数を受け取り、クライアントのキーで自分自身に署名し、正当なクライアントであるかどうかを確認できます(上記の手順1で)。

この署名では、クライアントとサーバーの両方が引数の順序に同意する必要があります(したがって、これらはまったく同じ文字列に署名します)。OAuth 1に関する主な不満の1つは、サーバーとクライアントは同じようにソートして署名します。これは面倒なコードであり、正しいか、ほとんど助けを借りずに401 Unauthorizedを取得します。これにより、クライアントを作成する際の障壁が高まります。

OAuth 2.0では、認証リクエストをSSL経由で実行する必要があるため、引数の並べ替えと署名を完全に行う必要がなくなります。クライアントはその秘密をサーバーに渡し、サーバーはそれを直接検証します。

サーバー->コンテンツプロバイダー接続にも同じ要件があります。これはOAuthサービスにアクセスするサーバーを作成するための1つの障壁を取り除くSSLであるためです。

これにより、上記の手順1、2、および5で作業が非常に簡単になります。

そのため、この時点で、サーバーにはユーザーと同等のユーザー名/パスワードである永続的なアクセストークンがあります。アクセストークンをリクエストの一部として(クエリ引数、HTTPヘッダー、またはPOSTフォームデータとして)渡すことにより、ユーザーに代わってコンテンツプロバイダーにリクエストを行うことができます。

コンテンツサービスがSSL経由でのみアクセスされる場合は、これで完了です。プレーンHTTP経由で利用できる場合は、何らかの方法でその永続的なアクセストークンを保護したいと思います。接続をスニッフィングする人はだれでも、ユーザーのコンテンツに永久にアクセスできます。

OAuth 2で解決される方法は、refresh tokenを使用することです。リフレッシュトークンは永続的なパスワードと同等になり、SSLでのみ送信されます。サーバーがコンテンツサービスにアクセスする必要がある場合、更新トークンを短命のアクセストークンに交換します。そのようにして、すべての盗聴可能なHTTPアクセスは、期限切れになるトークンを使用して行われます。 Googleは、OAuth 2 APIで5分の有効期限を使用しています。

そのため、更新トークンは別として、OAuth 2はクライアント、サーバー、コンテンツプロバイダー間のすべての通信を簡素化します。また、更新トークンは、コンテンツが暗号化されずにアクセスされている場合にセキュリティを提供するためにのみ存在します。

二本足認証

ただし、サーバーが自分のコンテンツへのアクセスを制御するだけでよい場合もあります。二本足認証により、クライアントはサーバーでユーザーを直接認証できます。

OAuth 2は、広く使用されていたOAuth 1の一部の拡張機能を標準化します。私が最もよく知っているのは、Twitterで xAuth として紹介されたものです。 OAuth 2で Resource Owner Password Credentials として表示できます。

基本的に、ユーザーの資格情報(ユーザー名とパスワード)を使用してクライアントを信頼できる場合、クライアントはそれらをアクセストークンのコンテンツプロバイダーと直接交換できます。これにより、モバイルアプリでOAuthがさらに便利になります。3脚認証では、コンテンツサーバーで認証プロセスを処理するためにHTTPビューを埋め込む必要があります。

OAuth 1では、これは公式の標準の一部ではなく、他のすべてのリクエストと同じ署名手順が必要でした。

リソースオーナーパスワード認証情報を使用してOAuth 2のサーバー側を実装しましたが、クライアントの観点から、アクセストークンの取得は簡単になりました。サーバーからアクセストークンを要求し、クライアントID/HTTP Authorizationヘッダーとフォームデータとしてのユーザーのログイン/パスワード。

利点:シンプルさ

したがって、実装者の観点から見ると、OAuth 2で見られる主な利点は、複雑さが軽減されていることです。リクエストの署名手順は必要ありません。これは厳密には難しくありませんが、確かに面倒です。これにより、サービスのクライアントとして機能するために必要な作業が大幅に削減されます。これは、(現代のモバイルの世界で)痛みを最小限に抑えたい場所です。サーバー→コンテンツプロバイダー側​​の複雑さが軽減されるため、データセンターでのスケーラビリティが向上します。

また、現在広く使用されているOAuth 1.0a(xAuthなど)のいくつかの拡張機能を標準に成文化しています。

313
Peter T

まず、OAuth認証で明確に示されているように

OAuth 2.0は認証プロトコルではありません。

アプリケーションにアクセスするユーザーのコンテキストでの認証は、現在のユーザーが誰であり、存在するかどうかをアプリケーションに伝えます。完全な認証プロトコルは、一意の識別子、電子メールアドレス、アプリケーションが「おはよう」と言ったときに何を呼び出すかなど、このユーザーに関する多くの属性もおそらく通知します。

ただし、OAuthは、アプリケーションにそれを伝えません。 OAuthは、ユーザーについてまったく何も言っておらず、ユーザーが自分の存在を証明した方法や、ユーザーがまだそこにいたとしても、それについても述べていません。 OAuthクライアントに関する限り、クライアントはトークンを要求し、トークンを取得し、最終的にそのトークンを使用してAPIにアクセスしました。誰がアプリケーションを承認したか、またはそこにユーザーさえいたかどうかについては何も知りません。

OAuthを使用したユーザー認証には、OAuth2と互換性のあるOpenID Connectの標準があります。

OpenID Connect IDトークンは、通常のOAuthアクセストークンとともにクライアントアプリケーションに与えられる署名付きJSON Webトークン(JWT)です。 IDトークンには、ユーザーの識別子(sub)、トークンを発行したIDプロバイダーの識別子(iss)、およびこのトークンが作成されたクライアントの識別子を含む、認証セッションに関するクレームのセットが含まれています( aud)。

Goでは、coreos/dex、OpenID Connect Identity(OIDC)、およびPluggable Connectorを使用したOAuth 2.0プロバイダーを確認できます。

この投稿からの回答 vonc

6
radhakrishnan

私はこの質問に少し違った方法で答えますが、主に@Peter Tがすべて答えたので、私は非常に正確で簡潔になります。

この規格から得られる主な利点は、2つの原則を尊重することです。

  1. 関心事の分離。
  2. 通常ビジネスに役立つWebアプリケーションから認証を分離します。

そうすることによって、

  1. シングルサインオンの代替手段を実装できます。1つのSTSを信頼するアプリケーションが複数ある場合。つまり、すべてのアプリケーションに対して1つのユーザー名です。
  2. Webアプリケーション(クライアント)を有効にして、ユーザーに属し、Webアプリケーション(クライアント)に属さないリソースにアクセスできます。
  3. 信頼できる第三者に認証プロセスを義務付けることができ、ユーザーの信頼性の検証について心配する必要はありません。
2
Assil