モバイルアプリのOAuthシークレット


137

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

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

別のアプローチは、それをサーバーに保存し、アプリを実行するたびにフェッチし、電話に保存しないことです。アプリにURLを含める必要があるため、これはほぼ同じです。

私が思いつくことができる唯一の実行可能な解決策は、最初に通常どおりにアクセストークンを取得し(できればアプリ内のWebビューを使用して)、次にすべての通信をサーバー経由でルーティングすることです。これにより、要求データにシークレットが追加されて通信しますプロバイダーと。繰り返しになりますが、私はセキュリティの初心者なので、これについて知識のある人々の意見を本当に聞きたいです。ほとんどのアプリは、セキュリティを保証するためにこれらの長さにしようとしているようには見えません(たとえば、Facebook Connectは、アプリ内の文字列にシークレットを挿入すると想定しているようです)。

もう1つ、秘密が最初にアクセストークンを要求することに関係しているとは思わないので、それは私たち自身のサーバーを関与させることなく実行できます。私は正しいですか?


わかりにくい場合は申し訳ありませんが、アプリケーションのデータベースにコードを保存する際の問題は何ですか?これらのトークンは、ユーザーが自分のアカウントを認証した後に生成および保存されるため、そのユーザーがモバイルデバイスにアクセスを保存してアクセスできるようにしたいと考えるのは安全です。
突く

ユーザーが自分のアカウント(Twitterなど)へのアクセスを許可した後でも、アクセスしようとしているサービスから取得したシークレットを使用する必要があります。このシークレットは、認証キーと他のいくつかのキーと一緒に、サーバーとのすべての通信で使用されます。そうです、あなたはアクセスキーを格納することができますが、一緒に使用される可能性があるため秘密は、保存すべきではないすべてのサービスを悪用するために認証キー。繰り返しますが、私はこれについてもっと知っている人々によって修正されてうれしいです。
Felixyz

1
OAuthは、元のユーザーのログインデータを保護する認証方法を提供します。これを可能にするために、一意のアプリケーションのキーの組み合わせでのみ機能する新しい一意のログインの組み合わせが生成されます。ユーザーのログインデータを保存することの大きな利点は、最初の認証は完全に安全であり、違反した場合でもユーザーは認証のアクセスを取り消すことができることです。もちろん、ユーザーが再認証する必要があるため、シークレットを保存しなくても意味がありません(アプリケーションにアクセスを許可するときにユーザーが望むことではありません)。
突く

@pokeユーザーがプロバイダーでアプリを承認するときに取得される認証キーは保存する必要がありますが、アプリをリリースする前にプロバイダーから受け取った秘密トークンは保存しないでください(デスクトップまたはモバイルアプリの場合。質問に記載されているように、キーをサーバーに保存できるWebアプリです)。
Felixyz 09

4
デスクトップアプリのoAuth--での例私の理解あたりとしてその非常に簡単スニフに/このようなツールを使ってHTTP / HTTPSトラフィック監視ieinspector.com/httpanalyzer/index.html したがって、あなたのトークンとトークンシークレットを両方非常に見つけることができます簡単に。したがって、唯一の保護はあなたの消費者秘密です。アプリ内の秘密がストアに格納されていて、誰かがそれを見つけることができる場合、他のアプリをアプリとして偽装することは子供の遊びになります。私が間違っていたら訂正してください。
Varun、2010年

回答:


38

はい、これは私たちが直面している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-based https://www.yammer.com/api_oauth_security_addendum.html


これは非常に興味深いことですが、私が恐れていたことを裏付けていますが、OAuthはデスクトップ/モバイルアプリにはそれほど優れていません。もちろん、攻撃者は最初に秘密を取得し、次に誰かの資格情報を盗聴する必要があるため、かなりの決断が必要になります。ピンソリューションはデスクトップでは問題ありませんが、モバイルimoでは強引です。
フェリクシー09

この問題はそれらに当てはまらないので、提案されたスキームはどのように付加価値Webサービスを助けますか?また、プロバイダーが新しいシークレットを生成する方法がわからない。これらの新しいシークレットを要求するには「マスターシークレット」が必要であるため、独自のサーバー(少なくとも、主な秘密)。ただし、もちろん、すべてのトラフィックを自分のサーバーにルーティングするよりも優れています。明確化は大歓迎です!そして、あなたの提案が進んだら、ここで更新してください!
フェリクシー09

5
気になるところ:プロキシサーバーへの呼び出しが正当なものであるとどう判断しますか?
davidtbernal 2011

1
notJimへの対応:コンシューマーシークレットの公開を許可する際の主なリスクは、悪意のある(または愚かな)アプリケーションがそれを使用して開発される可能性があることです。制御するWebアプリケーションを介してシークレットを必要とするすべての呼び出しをプロキシすることにより、使用しているAPIがシャットダウンすることを決定する前に、悪用のパターンを監視し、ユーザーまたはアクセストークンレベルでアクセスを取り消すことができる状態に戻りますサービス全体をダウンさせます。
準静的

私はここで準静的に同意します。oauth呼び出しを処理するには、SSL対応のブラウザーを使用する必要があります。これは、将来のセキュリティ更新プログラムの管理が容易であるなど、いくつかの理由から良いことであり、実際のアプリケーションでは、時間の経過とともに更新する必要はありません。ザックはTwitterがPINソリューションを提案していることを指摘していますが、私も実際に考えましたが、アプリケーションを信頼してコードを安全に取得することは信頼できないためです。PINとシークレットと共に最新の暗号化を使用した「ナンス」を使用して、Webサーバー経由でリクエストをプロキシすることをお勧めします。
マーク

18

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

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

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

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


2
「ある種のアプリIDを取得するためのプラットフォーム固有のメカニズム」について詳しく説明できますか?サーバーコンポーネントはどのようにしてクライアントの身元を確認しますか?これはクライアントプロビジョニングで実行できると思います。たとえば、新しい一意のSSL証明書を各クライアントに展開します。そういう意味ですか これよりも複雑な場合は、より詳細な記事を参照できますか?
Cheeso 2014

2
これがどのように行われることができるかについて話しているいくつかの警備員を思い出します。サーバーに送信して検証できる署名済みトークンを返すOSへの呼び出しがあります。詳細はわかりません。これは、いくつかの良い例を使用できるエラーです。
ディック・ハート2015年

2
@DickHardtしかし、このシナリオでは、モバイルアプリケーションが実際に自分のアプリであり、不正なアプリではないことをどのように確認しますか?
Rafael Membrives

11

1つの解決策は、OAuthシークレットをコードにハードコーディングすることですが、プレーンな文字列としてはできません。何らかの方法で難読化します-セグメントに分割し、オフセットによって文字をシフトし、回転します-これらのいずれかまたはすべてを実行します。クラッカーはバイトコードを分析して文字列を見つけることができますが、難読化コードは理解しにくい場合があります。

これは間違いのないソリューションではありませんが、安価なソリューションです。

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


1
はい、これは合理的だと思います。誰かが最初に消費者の秘密を抽出し、次に人々の資格情報を奪って何か意味のあることを行うには、多くの決断が必要です。注目度の高いアプリの場合はこれで十分かどうかはわかりませんが、平均的なアプリの場合は、実装時間とかなり小さなセキュリティの脅威とのバランスを取る必要があると思います。
フェリクシー、2009

7
必要なのは、1人のユーザーがその努力を発揮してから、秘密を公開または共有することだけです。シークレットが公開されると、乱用のためにサービスが完全にシャットダウンするリスクがあり、完全に制御できなくなります。
quasistoic 2012

8
難読化はセキュリティではありません。これは、開発者に誤った安心感を与えるため、まったくセキュリティがないよりも悪いです。en.wikipedia.org/wiki/Security_through_obscurity
Paul Legato 14年

8
「難読化はまったくセキュリティではありません。これは、開発者に誤った安心感を与えるため、まったくセキュリティがないよりも悪いです。」ナンセンス。難読化によってセキュリティが向上するとは誰も言っていません。しかし、apkでOAuthシークレットを配布する場合は、難読化する方がましです。難読化は、キー/シークレットをアプリ内に保存するときにGoogleが推奨するものでもあります。他に何もなければ、これらの対策はカジュアルなハッカーを寄せ付けないことで、何もないよりはましです。あなたのような包括的な声明は、不完全なセキュリティをセキュリティなしと見なします。それは単に真実ではありません。不完全は単に不完全です。
hungryghost

1
難読化は役に立ちません。どれだけシフトまたはエンコードしても、キーを一緒に作成し、それを使用してAPIリクエストを作成するためです。HTTPS暗号化を行う前に、APIを適切な場所に動的にフックして、送信しているリクエストをダンプするのはかなり簡単です。ですから、本当に可能な代替手段がない限り、アプリに秘密鍵を埋め込まないでください。
C0deH4cker 16

6

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

https(明らかに)を介してアプリケーションからアクセスできるサーバーが必要で、そのサーバーにシークレットを保存します。

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

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

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

注意

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

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


1
これはハッカーの生活を楽にしませんか?サーバーリソースにアクセスするには、技術的にはクライアントIDが必要です。サーバーがとにかくシークレットをリクエストに追加するからです。私は何かを逃していますか?
Hudi Ilfeld

@HudiIlfeldはい、何か不足しています:クライアントはサーバーにログインする必要があります。彼がログインしていない限り、サーバーは何も返しません。これを管理する1つの方法は、最初に資格情報を送信した後、サーバーがクライアントにアクセストークンを返し、クライアントが以降のすべての要求でこのアクセストークンを送信することです。ここには多くのオプションがあります。
グドラダイン

4

Authorization Code Grant Typeには、Proof Key for Code Exchange(PKCE)と呼ばれる新しい拡張機能があります。それを使用すると、クライアントシークレットは必要ありません。

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

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

https://oauth.net/2/pkce/から

詳細については、完全なRFC 7636またはこの短い紹介をご覧ください。


2

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

多分私は読んで何かに目を通しました、しかしインストールされたアプリとあなたのウェブアプリのユニークなキーを共有することはおそらく公式のインストールされたアプリの方法で「匿名」を使用するよりも安全であるようです。


2

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

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


サービスが「クライアント側フロー」をサポートしている場合。多くの場合は必要ありません。代わりに、このアクセストークンを取得するためにクライアントIDとクライアントシークレットが必要です。
Damian Yerrick

0

OAuthの使用経験はあまりありませんが、すべてのリクエストでユーザーのアクセストークンだけでなく、アプリケーションのコンシューマーキーとシークレットも必要になるとは限りません。そのため、誰かがモバイルデバイスを盗んでデータを取得しようとした場合でも、実際に何かを実行するには、アプリケーションキーとシークレットも必要になります。

OAuthの背後にある意図は、マッシュアップを持ったすべてのトム、ディック、およびハリーがTwitterの資格情報を平文で保存する必要がないようにするためだといつも思っていました。制限にもかかわらず、それはその問題をかなりうまく解決すると思います。また、iPhoneを念頭に置いて実際に設計されたわけでもありません。


おっしゃるとおり、OAuthは主にWebアプリを念頭に置いて設計されており、それが適切に機能すると私は確信しています はい、各リクエストに署名するにはコンシューマトークンとシークレットが必要です。問題はシークレットを保存する場所です。誰かがアクセスキーを盗んだ場合、取り消される可能性があるので大したことではありませんが、誰かがコンシューマキーを取得した場合、アプリのすべてのコピーが侵害されています。
フェリクシー09

OAuth 1では、各リクエストに署名する必要がありました。OAuth 2では、アクセストークンのみが必要です。トークンを取得する際には、どちらもキーとシークレットが必要です。
ディック・ハート2015年

0

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

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

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

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

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

技術に精通していない平均的なユーザーにとってはかなり怖いものです。そのようなことで、サインアップ完了率が高くなるとは思いません。

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


0

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

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

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

うまくいきますか?


3
良い考えですが、違います。クラッカーは、OS定数のアドレスを指すバイナリを見るだけです。
GrayB


0

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

OAuthに関しては、ええ、私はそれについてもっと考えるほど、私たちは少し詰まっています。多分これはそれを修正します。


1
wiki.developers.facebook.comは死んでいます。
Hugo、

0

これらのソリューションはどれも、モバイルデバイス(またはエミュレータ)から送信されたパケットを特定のハッカーが盗聴して、httpヘッダーのクライアントシークレットを表示することを防ぎます。

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

このようにして、シークレットが侵害されたとしても、ハッカーは最大5分間しかシークレットを使用できません。


-2

他の人が述べたように、デバイスにローカルにシークレットを保存することには実際の問題はないはずです。

その上、いつでもAndroidのUNIXベースのセキュリティモデルに依存できます。ファイルシステムに書き込んだものにアクセスできるのはアプリケーションだけです。アプリのデフォルトのSharedPreferencesオブジェクトに情報を書き込むだけです。

シークレットを取得するには、Androidフォンへのルートアクセスを取得する必要があります。


3
誰が言ったように?pokeのコメントを意味している場合は、秘密の!=認証キーの私の回答を参照してください。後者は安全に保管できますが、前者は保管できません。私はAndroidについては知りませんが、iPhoneへのrootアクセスを取得することは決して難しくありません。シークレットはアプリのすべてのインスタンスで同じであるため、攻撃者は1つのバイナリにアクセスするだけで済みます。また、デバイスでrootアクセスを取得できなかったとしても、他のバイナリを入手して、秘密のトークンを取り出すことができます。
フェリクシー09

1
追加するだけで、Androidスマートフォンのルート
権限を取得するの
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.