Androidにアクセストークンとシークレットを安全に保存する方法は?


123

Googleからメールと連絡先を取得するためにoAuthを使用します。ユーザーに毎回ログインしてアクセストークンとシークレットを取得するように要求したくありません。私が理解したことから、私はそれらを私のアプリケーションと一緒にデータベースまたはに保存する必要がありますSharedPreferences。しかし、私はそれでセキュリティ面について少し心配しています。トークンの暗号化と復号化は可能ですが、攻撃者がAPKとクラスを逆コンパイルして暗号化キーを取得するのは簡単です。
これらのトークンをAndroidに安全に保存するための最良の方法は何ですか?


1
コンシューマーキーとシークレットを保存するにはどうすればよいですか(ハードコンディングは保護されていません)?私はそれらにaccesstokenとsecretを要求する必要があります。oauthを使用する他の既存のアプリはどのようにそれを行いますか?うーん最後にoauthを使用すると、もっと多くのセキュリティ問題に対処する必要があります....コンシューマトークン/シークレットを安全に保持する必要があります。また、accesstokenとシークレットも保持する必要があります....暗号化されたユーザーのユーザー名/パスワードを保存するだけですか?...最後に、後者の方がいいですか?私はまだoauthがどのように優れているかまだわかりません...
yeahman

アクセストークンを格納するファイルを教えてください。私はAndroidを使い始めたばかりですが、サンプルプラスアプリを実行してみましたが、どこにも見つかりません[GoogleAuthUtil.getToken()メソッド]
Abhishek Kaushik

回答:


118

それらを共有設定として保存します。これらはデフォルトで非公開であり、他のアプリはそれらにアクセスできません。ルート権限を取得されたデバイスで、ユーザーがデバイスを読み取ろうとしているアプリへのアクセスを明示的に許可した場合、アプリはそれらを使用できる可能性がありますが、それを防ぐことはできません。暗号化については、ユーザーに毎回復号パスフレーズを入力するように要求する(したがって、資格情報をキャッシュする目的を無効にする)か、キーをファイルに保存する必要があり、同じ問題が発生します。

実際のユーザー名のパスワードの代わりにトークンを保存することにはいくつかの利点があります:

  • サードパーティのアプリはパスワードを知っている必要はなく、ユーザーはパスワードを元のサイト(Facebook、Twitter、Gmailなど)にのみ送信することを確認できます。
  • 誰かがトークンを盗んだとしても、パスワードを見ることはできません(ユーザーが他のサイトでも使用している可能性があります)。
  • トークンには通常、有効期限があり、一定の時間が経過すると有効期限が切れます
  • 侵害された疑いがある場合、トークンを取り消すことができます

1
返信のthx!しかし、コンシューマキーが侵害されたかどうかをどのようにして知ることができますか?lolそれは言うのは難しいでしょう...アクセストークンとシークレットを保存することについてはOK、OK私はそれらをsharedpreferencesに保存して暗号化しますが、コンシューマキーとシークレットはどうですか?それらをsharedpreferencesに保存することはできません(最初に、それをsharedpreferenceに保存するには、コンシューマキーとシークレットを明示的にコードに記述する必要があります)。
イェイマン

2
アプリにを(ある程度)難読化された方法で配置し、逆コンパイル後すぐに表示されないようにするか、キーとシークレットを持つ独自の認証プロキシWebアプリケーションを使用する必要があります。それらをアプリに配置する方が明らかに簡単です。アプリをクラックしようとするリスクが十分に低いと考えられる場合は、そのアプローチをとってください。ちなみに、上記のポイントはユーザーパスワード用です。コンシューマーキー/シークレットが侵害されていることがわかった場合は、それらも取り消すことができます(もちろん、アプリが破損します)。
Nikolay Elenkov

1
@NikolayElenkov:「暗号化に関しては、ユーザーに毎回復号化パスフレーズを入力するように要求する(したがって、資格情報をキャッシュする目的を無効にする)か、キーをファイルに保存する必要がありますが、同じ問題が発生します。」 。クラッカーがアプリを元に戻して暗号化の仕組みを理解した場合はどうなりますか?あなたの防御は破られるかもしれません。そのような情報(トークン、暗号化...)をネイティブコードを使用して保存することはベストプラクティスですか?
anhldbk 2014年

1
アプリのデータが消去されると、更新トークンが失われます。これは、おそらくユーザーが望んでいないことです。
RDS

1
これは現在、トークンを保存するための最良の方法ではありません!
Rahul Rastogi、

19

それらはAccountManagerに保存できます。これらの人によると、それはベストプラクティスと考えられています。

ここに画像の説明を入力してください

これが公式の定義です:

このクラスは、ユーザーのオンラインアカウントの一元化されたレジストリへのアクセスを提供します。ユーザーは資格情報(ユーザー名とパスワード)をアカウントごとに1回入力し、アプリケーションに「ワンクリック」承認でオンラインリソースへのアクセスを許可します。

AccountManagerの使用方法の詳細ガイド:

ただし、最終的にはAccountManagerはトークンをプレーンテキストとしてのみ保存します。そのため、AccountManagerに保存する前にシークレットを暗号化することをお勧めします。AESCryptAESCryptoなどのさまざまな暗号化ライブラリを利用できます

もう1つのオプションは、Concealライブラリを使用することです。Facebookにとって安全で、AccountManagerよりもはるかに使いやすいです。以下は、Concealを使用してシークレットファイルを保存するためのコードスニペットです。

byte[] cipherText = crypto.encrypt(plainText);
byte[] plainText = crypto.decrypt(cipherText);

2
隠蔽する良いヒント。とても使いやすいように見えます。そして、多くのユースケースで。
ラゴス2017

リンクからConcealが見つかりませんでした。非アクティブ化される可能性があります
user1114

9

SharedPreferences 自体は安全な場所ではありません。ルート権限を取得されたデバイスでは、すべてのアプリケーションのSharedPrefereces xmlを簡単に読み取って変更できます。したがって、トークンは比較的頻繁に期限切れになるはずです。ただし、トークンが1時間ごとに期限切れになったとしても、SharedPreferencesから新しいトークンが盗まれる可能性があります。Android KeyStoreは、SharedPreferencesやデータベースなどにトークンを保存するためにトークンを暗号化するために使用される暗号化キーの長期保存と取得に使用する必要があります。キーはアプリケーションのプロセス内に格納されないため、侵害されるのはより困難です。

そのため、場所よりも関連性が高いのは、暗号で署名された短命のJWTを使用したり、Android KeyStoreを使用して暗号化したり、安全なプロトコルで送信したりすることなどです。


9
では、それらをどこに保存できますか?
Milind Mevada

3
  1. Android StudioのProjectペインから「Project Files」を選択し、プロジェクトのルートディレクトリに「keystore.properties」という名前の新しいファイルを作成します。

ここに画像の説明を入力してください

  1. 「keystore.properties」ファイルを開き、アクセストークンとシークレットをファイルに保存します。

ここに画像の説明を入力してください

  1. 次に、アクセストークンとシークレットをアプリモジュールのbuild.gradleファイルに読み込みます。次に、アクセストークンとシークレットのBuildConfig変数を定義して、コードから直接アクセスできるようにする必要があります。あなたのbuild.gradleは以下のようになります。

    ... ... ... 
    
    android {
        compileSdkVersion 26
    
        // Load values from keystore.properties file
        def keystorePropertiesFile = rootProject.file("keystore.properties")
        def keystoreProperties = new Properties()
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    
        defaultConfig {
            applicationId "com.yourdomain.appname"
            minSdkVersion 16
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            // Create BuildConfig variables
            buildConfigField "String", "ACCESS_TOKEN", keystoreProperties["ACCESS_TOKEN"]
            buildConfigField "String", "SECRET", keystoreProperties["SECRET"]
        }
    }
  2. 次のように、コードでアクセストークンとシークレットを使用できます。

    String accessToken = BuildConfig.ACCESS_TOKEN;
    String secret = BuildConfig.SECRET;

この方法では、プロジェクト内にアクセストークンとシークレットをプレーンテキストで保存する必要はありません。そのため、誰かがAPKを逆コンパイルしても、外部ファイルからそれらをロードしているため、アクセストークンとシークレットを取得することはありません。


1
プロパティファイルを作成する代わりにハードコーディングを行うことに違いはないようです。
Dzshean

実行時にトークンを書きたいのですが、アプリを開くと毎回トークンが変更される可能性があります。
Rehan Sarwar

1
これは、APIアクセストークンのようないくつかのトークンを格納するための非常に良い方法です。ユーザーの資格情報を保存する場合は、NDKの方が適しています。
エリック

6
これは、アプリケーションに機密情報を保存する方法とはまったく異なります。このアプローチを使用してリポジトリにデータが含まれていない場合でも(データはビルドプロセスに注入されます)、単純な逆コンパイル後にすべての人が見ることができるプレーンテキストのトークン/シークレットを含むBuildConfigファイルが生成されます。
Hrafn

-1

さて、あなたは2つのオプションに従うことによってあなたのアクセストークンを保護することができます。

  1. アクセストークンをリバースしないAndroidキーストアに保存してください。
  2. トークンを保存するいくつかの計算でNDK関数を使用し、NDKを元に戻すのが非常に難しいc ++コードで使用する
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.