146 votes

Comment stocker de manière sécurisée un jeton d'accès et un secret dans Android ?

Je vais utiliser oAuth pour récupérer les mails et les contacts de google. Je ne veux pas demander à l'utilisateur de se connecter à chaque fois pour obtenir un jeton d'accès et un secret. D'après ce que j'ai compris, je dois les stocker dans mon application, soit dans une base de données, soit dans une base de données. SharedPreferences . Mais je suis un peu inquiet quant aux aspects de sécurité. J'ai lu que vous pouviez crypter et décrypter les tokens mais il est facile pour un attaquant de décompiler votre apk et vos classes et d'obtenir la clé de cryptage.
Quelle est la meilleure méthode pour stocker ces jetons en toute sécurité dans Android ?

136voto

Nikolay Elenkov Points 32843

Les stocker en tant que préférences communes . Celles-ci sont par défaut privées, et les autres applications ne peuvent pas y accéder. Sur un appareil rooté, si l'utilisateur autorise explicitement l'accès à une application qui tente de les lire, l'application peut être en mesure de les utiliser, mais vous ne pouvez pas vous en prémunir. En ce qui concerne le cryptage, il faut soit demander à l'utilisateur d'entrer la phrase de passe de décryptage à chaque fois (ce qui va à l'encontre de l'objectif de mise en cache des informations d'identification), soit enregistrer la clé dans un fichier, ce qui pose le même problème.

Il y a quelques avantages à stocker des jetons au lieu du mot de passe du nom d'utilisateur :

  • Les applications tierces n'ont pas besoin de connaître le mot de passe et l'utilisateur peut être sûr qu'il ne l'envoie qu'au site d'origine (Facebook, Twitter, Gmail, etc.).
  • Même si quelqu'un vole un jeton, il n'a pas accès au mot de passe (que l'utilisateur peut également utiliser sur d'autres sites).
  • Les jetons ont généralement une durée de vie et expirent après un certain temps.
  • Les jetons peuvent être révoqués si vous pensez qu'ils ont été compromis.

31voto

aldok Points 4348

Vous pouvez les stocker dans Gestionnaire de compte . Selon eux, il s'agit d'une bonne pratique.

enter image description here

Voici la définition officielle :

Cette classe permet d'accéder à un registre centralisé de l'identité de l'utilisateur de l'utilisateur. L'utilisateur entre ses données d'identification (nom d'utilisateur et mot de passe) une fois par compte, ce qui permet aux applications d'accéder aux ressources en ligne. en un seul clic.

Pour un guide détaillé sur l'utilisation de AccountManager :

Cependant, en fin de compte, AccountManager ne stocke votre jeton que sous forme de texte brut. Je vous conseille donc d'encrypter vos secrets avant de les stocker dans AccountManager. Vous pouvez utiliser différentes bibliothèques de cryptage comme AESCrypt o AESCrypto

Une autre option consiste à utiliser Dissimuler la bibliothèque . Il est suffisamment sûr pour Facebook et beaucoup plus facile à utiliser que AccountManager. Voici un extrait de code permettant d'enregistrer un fichier secret à l'aide de Conceal.

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

19voto

apex39 Points 505

Préférences partagées n'est pas un lieu sûr lui-même. Sur un appareil enraciné, nous pouvons facilement lire et modifier les xml de SharedPrefereces de toutes les applications. Les jetons doivent donc expirer relativement souvent. Mais même si un token expire toutes les heures, des tokens plus récents peuvent toujours être volés à partir de SharedPreferences. Android KeyStore doit être utilisé pour le stockage à long terme et la récupération des clés cryptographiques qui seront utilisées pour crypter nos jetons afin de les stocker, par exemple, dans SharedPreferences ou dans une base de données. Les clés ne sont pas stockées dans le processus d'une application. sont plus difficiles à compromettre.

Ainsi, plus qu'un lieu, c'est la manière dont ils peuvent être sécurisés qui importe, par exemple en utilisant des JWT à courte durée de vie signés cryptographiquement, en les chiffrant à l'aide d'Android KeyStore et en les envoyant à l'aide d'un protocole sécurisé.

4voto

kfrye Points 1

En guise de mise à jour tardive de cette question, vous pouvez désormais utiliser EncryptedSharedPreferences (préférences partagées cryptées) pour stocker les données en toute sécurité. L'interface est très similaire, sauf que vous devez également générer une MasterKey.

La plupart des documents concernant EncryptedSharedPreferences utilisent MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC, mais il semble que cette méthode soit obsolète au profit de MasterKey.Builder .

private var masterKeyAlias = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build() 

private val preferences = EncryptedSharedPreferences.create(
            context,
            "auth_token_secured",
            masterKeyAlias,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        )

var authToken: String?
    get() = preferences.getString("auth_token", "")
    set(value) = preferences.edit().putString("auth_token", value).apply()

3voto

  1. Dans le panneau Projet de votre Android Studio, sélectionnez "Fichiers du projet" et créez un nouveau fichier nommé "keystore.properties" dans le répertoire racine de votre projet.

enter image description here

  1. Ouvrez le fichier "keystore.properties" et enregistrez votre jeton d'accès et votre secret dans le fichier.

enter image description here

  1. Chargez maintenant le jeton d'accès et le secret dans votre application du module build.gradle fichier. Vous devez ensuite définir la variable BuildConfig pour votre jeton d'accès et votre secret afin de pouvoir y accéder directement à partir de votre code. Votre build.gradle peut ressembler à ce qui suit :

    ... ... ... 
    
    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. Vous pouvez utiliser votre jeton d'accès et votre secret dans votre code comme suit :

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

De cette façon, vous n'avez pas besoin de stocker le jeton d'accès et le secret en texte clair dans votre projet. Ainsi, même si quelqu'un décompile votre APK, il n'obtiendra jamais votre Token d'accès et votre Secret car vous les chargez à partir d'un fichier externe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X