web-dev-qa-db-ja.com

OAuth2-リソース所有者パスワード資格情報付与

OAuth2仕様では、リソース所有者のパスワード資格情報付与タイプと承認フロー ここ について説明しています。 「信頼できる」クライアントアプリケーションのみがこの許可の使用を許可されることを理解しています。たとえば、「公式」iPhoneまたはAndroidバックエンドAPIによるクライアントアプリケーション。

私の質問は、このクライアントアプリケーションであると主張するソースからの要求が信頼できることをどのように保証できるかです。例えば:

  • 私は自分のAndroidアプリをOAuth2サーバーにclient_idがAndroid_appで、付与タイプpasswordにアクセスして(つまり、リソース所有者のパスワード認証情報)で)登録しました。

  • Androidアプリはクライアントアプリケーションであるため、クライアントを「秘密」に保つことは信頼されておらず、クライアントに割り当てられていないと想定しています。アプリ構成にはclient_idとgrant_typeが含まれています認証エンドポイントと同様に。

  • ユーザーがアプリを逆コンパイル/解凍/難読化解除し、client_idとエンドポイントを見つけた

クライアントがクライアントIDを使用してそのエンドポイントに認証リクエストを送信するのを停止するにはどうすればよいですか?クライアントにclient_secretを割り当てることを検討しますが、ユーザーがアプリでそれを見つけるだけで問題が解決しないようです。

19
sf13579

これらは本当に2つの質問です。


このクライアントアプリケーションであると主張するソースからのリクエストが信頼できることをどのように保証できますか?

できません。仕様では

リソース所有者のパスワード資格情報付与タイプは、リソース所有者がクライアントと信頼関係を持っている場合に適しています[...]

リソース所有者(別名ユーザー)は、承認サーバーではなくクライアントを信頼するかどうかを決定する必要があります。ユーザーがサードパーティのアプリを信頼して、プレーンなパスワードを入力するように決定した場合、サードパーティのアプリが信頼できるかどうかを自動的に検出することはできません。


クライアントがクライアントIDを使用してそのエンドポイントへの認証要求を行うのを停止するのは何ですか?クライアントにclient_secretを割り当てることを検討しますが、ユーザーがアプリでそれを見つけることができるため、問題が解決しないようです。

OAuth2は 機密クライアントと公開クライアント を区別します。機密クライアントは「資格情報の機密性を維持できる」、たとえばサーバー側で別のクライアントにアクセスするWebアプリケーションです。

ネイティブアプリケーション(Androidアプリなど)は、パブリッククライアントとして明示的に言及されています。

ネイティブアプリケーションは、リソース所有者が使用するデバイスにインストールおよび実行されるパブリッククライアントです。リソースの所有者はプロトコルデータと資格情報にアクセスできます。アプリケーションに含まれるクライアント認証資格情報はすべて抽出できると想定されています。 [...]

したがって、クライアントシークレットは、ほとんどのユースケースでネイティブアプリケーションにセキュリティを追加しません。

10

このクライアントアプリケーションであると主張するソースからのリクエストが信頼できることをどのように保証できますか?

できません。

別のSO answer を引用するには:

ただし、モバイルでは、アプリケーションは既に信頼されており、ユーザーが選択したアプリケーションをインストールすると、ユーザーはアプリケーションを完全に保護することはできません。インストールして信頼することにしました。

クライアントがクライアントIDを使用してそのエンドポイントに認証リクエストを送信するのを止めるにはどうすればよいですか?

何もない。

たとえば、ユーザーのユーザー名/パスワードの保護のみに集中できます。

  • アプリ内に保存しないでください。
  • 公式アプリの入手先と、認証情報を求める他のアプリを信頼すべきではない理由を明確に説明して、ユーザーを教育します。

少し説明:

リソースにアクセスするために、アプリはアクセストークン(および最終的にはオプションの更新トークン)を取得する必要があります。

アクセストークンを取得するには、ユーザー名とパスワードを含む最初のリクエストをエンドポイントに送信する必要があります。注:client_idおよびclient_secretは、機密クライアント、またはクライアント資格情報が発行されたすべてのクライアントにのみ必須です。

そのため、悪意のあるアプリは、ユーザー名とパスワードを取得するまでリソースにアクセスできません。アクセスしないと、アクセストークンを取得できません。公式アプリのIDを使用していても。

4
thomas.g

提供された例は、あなたが言及した正確な理由から実際には非常に悪い例です-攻撃者はクライアントの秘密を抽出してクライアントになりすますことができます。

この許可のセキュリティは、クライアントシークレットをどれだけ適切に保護できるかに依存しています。さらに、攻撃者が途中で男を作成してリクエストから秘密を抽出することができないように、それはチャネルをどれだけうまく保護できるかに依存しています。これらの両方を保護できれば、かなり良い状況にありますが、モバイルアプリの場合、それを行うのは非常に困難です。

あなたの質問に答えるために:あなたは本当にできない。これらの問題のいくつかは、次の方法で軽減できます。

  • アプリケーションのインスタンスごとに一意のクライアントIDとシークレットを使用するが、管理が非常に複雑になる
  • または、信頼できるハードウェアストアにシークレットを保存できますが、プロトコルにはシークレットが逐語的に必要です
  • または、クライアントシークレットによって署名されたJWTまたはSAMLトークンを使用するなど、トークンベースのクライアント識別子を使用するようにプロトコルを変更して、シークレットの代わりにシークレットによって署名された短期間のアサーションが渡されるようにすることもできます。

これらすべてを一緒に追加すると、クライアントを特定するためのかなり確かな方法がありますが、間違いなく確実ではなく、明らかに欠点があります。管理性がPITAであり、最初の秘密の交換をどのように行うのか、などです。

1
Steve