web-dev-qa-db-ja.com

OAuthモバイルアプリの秘密

OAuthプロトコルを使用する場合、委任先のサービスから取得したシークレット文字列が必要です。これをWebアプリで実行している場合は、単にシークレットをデータベースに保存できますまたはファイルシステム上ですが、モバイルアプリ(またはデスクトップアプリ)でそれを処理する最良の方法は何ですか?

文字列をアプリに保存することは、誰かが簡単に見つけて悪用する可能性があるため、明らかに良くありません。

別のアプローチは、サーバーに保存し、実行ごとにアプリに取得させることです。電話には保存しません。アプリにURLを含める必要があるため、これはほとんど同じです。

私が思いつく唯一の実行可能な解決策は、最初に通常どおりアクセストークンを取得し(アプリ内のWebビューを使用することが好ましい)、その後、サーバーを介してすべての通信をルーティングし、リクエストデータに秘密を追加して通信することですプロバイダーと。それからまた、私はセキュリティの初心者なので、これに関する知識のある人の意見を聞きたいです。セキュリティを保証するために、ほとんどのアプリがこれらの長さになるとは思えません(たとえば、Facebook Connectは、アプリ内で文字列に秘密を入れることを前提としているようです)。

もう1つは、シークレットが最初にアクセストークンの要求に関与しているとは思わないため、独自のサーバーを使用せずに実行できることです。私は正しいですか?

129
Felixyz

はい、これは私たちが直面しているOAuthデザインの問題です。すべての呼び出しを自分のサーバー経由でプロキシすることを選択しました。OAuth OAuthを変更せずに発見した問題に対する完全な解決策はありません。

あなたがそれについて考えて、なぜ私たちが秘密を持っているのかという質問をするなら、ほとんどはアプリのプロビジョニングと無効化のためです。シークレットが侵害された場合、プロバイダーはアプリ全体を実際に取り消すことができます。デスクトップアプリにシークレットを埋め込む必要があるため、ややこしいです。

解決策は、デスクトップアプリごとに異なる秘密を保持することです。 OAuthはこの概念を簡単にしません。1つの方法は、ユーザーが自分で秘密を作成し、デスクトップアプリに自分でキーを入力することです(一部のFacebookアプリは長い間、ユーザーに行ってカスタムクイズとがらくたを設定するためにfacebookを作成させます。これはユーザーにとって素晴らしい経験ではありません。

OAuthの委任システムの提案に取り組んでいます。コンセプトは、プロバイダーから取得した独自のシークレットキーを使用して、独自のデスクトップクライアント(基本的に各デスクトップアプリに1つ)に独自の委任シークレットを発行し、認証プロセス中にそのキーをトップレベルに送信することです私たちにコールバックし、私たちと再検証するプロバイダー。このようにして、各デスクトップクライアントに発行する独自の秘密を無効にすることができます。 (これがSSLからどのように機能するかを多く借用しています)。このシステム全体は、サードパーティのWebサービスへの呼び出しを渡す付加価値Webサービスにも最適です。

トップレベルのプロバイダーが新しい委任されたシークレットを生成して取り消すためのAPIを提供している場合、委任検証コールバックなしでプロセスを実行することもできます。 Facebookは、Facebookアプリでユーザーがサブアプリを作成できるようにすることで、同様のことを行っています。

この問題に関するオンラインでの講演がいくつかあります。

http://blog.atebits.com/2009/02/fixing-oauth/http://groups.google.com/group/Twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

TwitterとYammerのソリューションは、認証ピンソリューションです。 https://dev.Twitter.com/oauth/pin-basedhttps://www.yammer.com/api_oauth_security_addendum.html

34
Zac Bowling

OAUth 2.0を使用すると、サーバーにシークレットを保存できます。サーバーを使用してアクセストークンを取得し、アプリに移動して、アプリからリソースに直接呼び出すことができます。

OAuth 1.0(Twitter)の場合、API呼び出しを行うにはシークレットが必要です。サーバーを介した呼び出しのプロキシは、シークレットが侵害されないようにする唯一の方法です。

どちらも、サーバーコンポーネントがそれを呼び出しているクライアントであることを認識する何らかのメカニズムを必要とします。これは、インストール時に行われ、プラットフォーム固有のメカニズムを使用して、サーバーへの呼び出しで何らかの種類のアプリIDを取得する傾向があります。

(私はOAuth 2.0仕様の編集者です)

18
Dick Hardt

1つの解決策は、コードにOAuthシークレットをハードコーディングしますが、プレーンストリングとしてnotです。何らかの方法で難読化-セグメントに分割し、文字をシフトしますクラッカーはバイトコードを分析して文字列を見つけることができますが、難読化コードはわかりにくい場合があります。

これは絶対確実な解決策ではなく、安価な解決策です。

エクスプロイトの価値に応じて、一部の天才クラッカーはより長い時間をかけてあなたの秘密のコードを見つけることができます。前述のサーバー側ソリューションのコスト、クラッカーが秘密のコードを見つけるためにより多くの労力を費やすインセンティブ、実装可能な難読化の複雑さなどの要因を検討する必要があります。

10
Jayesh

アプリケーション内にシークレットを保存しないでください。

アプリケーションがhttps(明らかに)でアクセスできるサーバーを用意し、そのサーバーに秘密を保存する必要があります。

誰かがモバイル/デスクトップアプリケーション経由でログインしたい場合、アプリケーションは単にリクエストをサーバーに転送し、サーバーはそのシークレットを追加してサービスプロバイダーに送信します。サーバーは、アプリケーションが成功したかどうかを通知できます。

次に、サービスから機密情報(facebook、google、Twitterなど)を取得する必要がある場合、アプリケーションはサーバーに問い合わせると、サーバーはアプリケーションが正しく接続されている場合にのみそれをアプリケーションに提供します。

サーバーに保存する以外のオプションはありません。クライアント側で安全なものはありません。

ただし、これは悪意のあるクライアントからのみ保護しますが、悪意のあるクライアントからは保護せず、他の悪意のあるクライアント(フィッシング)からは保護しません...

OAuthは、デスクトップ/モバイルよりもブラウザーではるかに優れたプロトコルです。

5
Gudradain

コード交換用の証明鍵(PKCE)と呼ばれる認証コード付与タイプに新しい拡張機能があります。これにより、クライアントシークレットは必要ありません。

PKCE(RFC 7636)は、クライアントシークレットを使用しないパブリッククライアントを保護する手法です。

これは主にネイティブアプリとモバイルアプリで使用されますが、この手法はどの公開クライアントにも適用できます。認証サーバーによる追加サポートが必要なため、特定のプロバイダーでのみサポートされます。

from https://oauth.net/2/pkce/

詳細については、完全な RFC 7636 または この短い紹介 を読むことができます。

2
Johannes Filter

OAuth 2.0を使用すると、クライアント側のフローを使用してアクセストークンを取得し、このアクセストークンを使用して以降のすべてのリクエストを認証できます。その後、シークレットはまったく必要ありません。

これを実装する方法の素敵な説明はここにあります: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

2
Joel Richard

考えるべきことがあります。 Googleでは、ドメインを登録して一意のキーを生成するWebアプリと、「匿名」キーを使用するインストール済みアプリに対して、OAuthの2つの方法を提供しています。

読み物で何かを説明したかもしれませんが、インストールされたアプリとWebアプリの一意のキーを共有することは、公式のインストールされたアプリメソッドで「匿名」を使用するよりもおそらく安全であるようです。

2
YiddishNinja

私はFelixyzに同意します。 OAuth Basic Authよりも優れていますが、モバイルアプリの優れたソリューションになるまでにはまだ長い道のりがあります。OAuth Google App Engineアプリに対して携帯電話アプリを認証するモバイルデバイスでコンシューマシークレットを確実に管理できないという事実は、デフォルトでは「匿名」アクセスを使用することを意味します。

Google App Engine OAuth実装のブラウザ認証ステップは、次のようなテキストを含むページに移動します:「サイト<some-site>は、製品のGoogleアカウントへのアクセスを要求しています以下通り"

YourApp(yourapp.appspot.com)-Googleと提携していません

カスタムスキームを使用してコールバックをインターセプトする場合、Androidで指定できるコールバックURLで使用されるドメイン/ホスト名から<some-site>を取得します。 「匿名」アクセスを使用するか、コンシューマシークレットが危険にさらされると、だれでもユーザーを欺いてgaeアプリへのアクセスを許可するコンシューマを作成できます。

Google OAuth認証ページには、「匿名」、コンシューマシークレット、または公開キーのいずれを使用しているかに応じて3つのレベルの重大度を持つ多くの警告も含まれています。

技術的に精通していない平均的なユーザーにとってはかなり怖いものです。こういった種類のものでは、サインアップ完了率が高いとは思わない。

このブログ投稿では、インストールされたアプリでコンシューマシークレットがどのように機能しないかを明らかにしています。 http://hueniverse.com/2009/02/should-Twitter-discontinue-their-basic-auth-api/

0
Martin Bayly

これらのソリューションでは、ハッカーがモバイルデバイス(またはエミュレーター)から送信されたパケットをスニッフィングして、httpヘッダーのクライアントシークレットを表示することを防ぐことはできません。

1つの解決策は、プライベート2ウェイ暗号化キーとアルゴリズムで暗号化されたタイムスタンプで構成される動的な秘密を保持することです。次に、サービスは秘密を解読し、タイムスタンプが+/- 5分かどうかを判断します。

このようにして、たとえ秘密が危殆化されたとしても、ハッカーは最大5分間しか秘密を使用できません。

0
Maximvs

ここで、モバイルアプリケーションにoAuth情報を保存する安全な方法に答えがあります

https://stackoverflow.com/a/17359809/99848

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/securelystoringoauthkeysiniosapplication

0
Boobalan

OAuth-の豊富な経験はありませんが、すべてのリクエストがユーザーのアクセストークンだけでなく、アプリケーションコンシューマキーとシークレットも必要とするわけではありませんか?モバイルデバイスを盗み、そこからデータを取得しようとすると、実際に何でもできるようにするにはアプリケーションキーとシークレットも必要になります。

OAuthの背後にある意図は、マッシュアップを持つすべてのTom、Dick、HarryがTwitterの認証情報をクリアに保存する必要がないようにするためだと思っていました。また、実際にはiPhoneを念頭に置いて設計されていませんでした。

0
bpapa

また、モバイルOAuth=認証、および一般的にアプリケーションバンドル内にシークレットを保存するためのソリューションを考えています。

そして、おかしなアイデアが思いつきました。最も簡単なアイデアは、バイナリ内に秘密を保存することですが、何らかの方法で難読化されます。つまり、暗号化された秘密を保存します。つまり、秘密を解読するためのキーを保存する必要があるということです。ただし、すでにOSにあるキーを使用しないでください。つまり、アプリケーションではなくOSによって定義されています。

したがって、私の考えを明確にするために、OSによって定義された文字列を選択するというのは、どの文字列でも構いません。次に、この文字列をキーとして使用してシークレットを暗号化し、アプリに保存します。次に、実行時に、OS定数であるキーを使用して変数を復号化します。ハッカーがバイナリを覗き込むと、暗号化された文字列が表示されますが、キーは表示されません。

それは機能しますか?

0
Daniel Thorpe

FacebookはOAuth厳密に言えば(まだ)実装していませんが、iPhoneアプリに秘密を埋め込まない方法を実装しています: https://web.archive .org/web/20091223092924/http://wiki.developers.facebook.com/index.php/Session_Proxy

OAuthについては、そう考えると、少し詰まっています。多分 this で修正されるでしょう。

0
oliland