Comment stocker en toute sécurité le jeton d'accès et le secret dans Android?

123

Je vais utiliser oAuth pour récupérer les e-mails et les contacts de Google. Je ne veux pas demander à chaque fois à l'utilisateur de se connecter pour obtenir un jeton d'accès et un secret. D'après ce que j'ai compris, j'ai besoin de les stocker avec mon application soit dans une base de données, soit SharedPreferences. Mais je suis un peu inquiet pour les aspects de sécurité avec cela. J'ai lu que vous pouvez crypter et décrypter les jetons, mais il est facile pour un attaquant de simplement 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é sur Android?

Oui mon gars
la source
1
Comment puis-je stocker la clé et le secret du consommateur (leur connexion en dur n'est pas sécurisée)? J'ai besoin d'eux pour demander l'accès et le secret .. comment les autres applications existantes utilisant oauth le font-elles? hmm enfin avec oauth, vous devez vous occuper de beaucoup plus de problèmes de sécurité pour moi .... je dois garder le jeton / secret du consommateur en toute sécurité, ainsi que l'accès et le secret .... enfin, ce ne serait pas plus simple de stocker simplement le nom d'utilisateur / mot de passe de l'utilisateur crypté? ... au final, ce dernier n'est-il pas meilleur? Je ne vois toujours pas comment oauth est meilleur ...
yeahman
pouvez-vous me dire .. quel fichier stocke le jeton d'accès ?? Je suis nouveau sur Android et j'ai essayé d'exécuter l'application Sample Plus, mais je ne trouve cela nulle part [méthode GoogleAuthUtil.getToken ().]
Abhishek Kaushik

Réponses:

117

Stockez-les en tant que préférences partagées . Ceux-ci sont par défaut privés et les autres applications ne peuvent pas y accéder. Sur un appareil enraciné, si l'utilisateur autorise explicitement l'accès à une application qui tente de les lire, l'application pourra peut-être les utiliser, mais vous ne pouvez pas vous protéger contre cela. En ce qui concerne le chiffrement, vous devez soit demander à l'utilisateur de saisir la phrase de passe de déchiffrement à chaque fois (ce qui va à l'encontre du but de la mise en cache des informations d'identification), soit enregistrer la clé dans un fichier, et vous obtenez le même problème.

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

  • Les applications tierces n'ont pas besoin de connaître le mot de passe et l'utilisateur peut être sûr de ne l'envoyer qu'au site d'origine (Facebook, Twitter, Gmail, etc.)
  • Même si quelqu'un vole un jeton, il ne peut pas voir le 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
Nikolay Elenkov
la source
1
merci pour la réponse! mais comment savoir si ma clé client a été compromise? lol ce sera difficile à dire .. ok pour stocker le jeton d'accès et le secret, ok je les sauvegarde dans les préférences partagées et les crypter, mais qu'en est-il de la clé et du secret du consommateur? Je ne peux pas les stocker dans sharedpreferences (j'aurais besoin d'écrire explicitement la clé de consommateur et le secret dans le code pour l'enregistrer dans sharedpreference en premier lieu) .. ne sais pas si vous comprenez ce que je veux dire.
yeahman
2
Vous devez soit les mettre dans l'application de manière (quelque peu) obscure, afin qu'ils ne soient pas immédiatement visibles après la décompilation, soit utiliser votre propre application Web proxy d'authentification qui a la clé et le secret. Les mettre dans l'application est évidemment plus facile, et si vous pensez que le risque que quelqu'un tente de pirater votre application soit suffisamment faible, adoptez cette approche. BTW, les points ci-dessus concernent le mot de passe de l'utilisateur. Si vous découvrez que votre clé / secret client a été compromis, vous pouvez également les révoquer (cela, bien sûr, endommagera votre application).
Nikolay Elenkov
1
@NikolayElenkov: Vous avez écrit "En ce qui concerne le chiffrement, vous devez soit demander à l'utilisateur de saisir la phrase de passe de déchiffrement à chaque fois (ce qui va à l'encontre du but de la mise en cache des informations d'identification), soit enregistrer la clé dans un fichier, et vous obtenez le même problème." . Et si les crackers inversaient votre application pour avoir un aperçu du fonctionnement du cryptage? Votre défense peut être brisée. Est-ce une bonne pratique de stocker de telles informations (jeton, cryptage ...) en utilisant du code natif?
anhldbk
1
Si les données de l'application sont effacées, le jeton d'actualisation est perdu, ce qui n'est probablement pas ce que l'utilisateur souhaitait.
rds
1
Ce n'est plus la meilleure façon de stocker des jetons de nos jours!
Rahul Rastogi
19

Vous pouvez les stocker dans AccountManager . C'est considéré comme la meilleure pratique selon ces gars.

entrez la description de l'image ici

Voici la définition officielle:

Cette classe permet d'accéder à un registre centralisé des comptes en ligne de l'utilisateur. L'utilisateur entre les informations d'identification (nom d'utilisateur et mot de passe) une fois par compte, accordant aux applications l'accès aux ressources en ligne avec une approbation "en un clic".

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

Cependant, à la fin, AccountManager stocke uniquement votre jeton sous forme de texte brut. Donc, je suggérerais de crypter votre secret avant de les stocker dans AccountManager. Vous pouvez utiliser diverses bibliothèques de chiffrement comme AESCrypt ou AESCrypto

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

byte[] cipherText = crypto.encrypt(plainText);
byte[] plainText = crypto.decrypt(cipherText);
Aldok
la source
2
Bonne astuce qui cache. Semble très facile à utiliser. Et pour de nombreux cas d'utilisation.
lagos
Impossible de trouver Conceal via le lien. Il peut être désactivé
user1114 le
10

SharedPreferences n'est pas un emplacement sécurisé en lui-même. Sur un appareil enraciné, nous pouvons facilement lire et modifier les fichiers XML SharedPrefereces de toutes les applications. Les jetons devraient donc expirer relativement fréquemment. Mais même si un jeton expire toutes les heures, les nouveaux jetons peuvent toujours être volés à 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 une base de données. Les clés ne sont pas stockées dans le processus d'une application, elles sont donc plus difficiles à compromettre.

Donc, plus pertinent qu'un lieu, c'est comment ils peuvent être eux-mêmes sécurisés, par exemple en utilisant des JWT de courte durée signés cryptographiquement, en les chiffrant à l'aide d'Android KeyStore et en les envoyant avec un protocole sécurisé

apex39
la source
9
Alors où pouvons-nous les stocker?
Milind Mevada
2
  1. Dans le volet Projet de votre Android Studio, sélectionnez "Fichiers de projet" et créez un nouveau fichier nommé "keystore.properties" dans le répertoire racine de votre projet.

entrez la description de l'image ici

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

entrez la description de l'image ici

  1. Maintenant charger la lecture du jeton d' accès et secret dans votre application du module build.gradle fichier. Ensuite, vous devez définir la variable BuildConfig pour votre jeton d'accès et secret afin que vous puissiez y accéder directement à partir de votre code. Votre build.gradle peut ressembler à ceci:

    ... ... ... 
    
    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 ceci:

    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 brut dans votre projet. Ainsi, même si quelqu'un décompile votre APK, il n'obtiendra jamais votre jeton d'accès et votre secret car vous les chargez à partir d'un fichier externe.

Zahidur Rahman Faisal
la source
1
Il semble qu'il n'y ait aucune différence entre la création d'un fichier de propriétés et le codage en dur.
Dzshean
Je veux écrire un jeton au moment de l'exécution peut-être que mon jeton est modifié à chaque fois que j'ouvre mon application.
Rehan Sarwar
1
C'est un très bon moyen de stocker certains jetons comme les jetons d'accès API. si vous souhaitez stocker les informations d'identification de l'utilisateur, le NDK est un meilleur moyen.
Eric
7
Ce n'est absolument pas ainsi que vous devez procéder pour stocker des informations sensibles dans votre application! Même si le référentiel ne contient pas les données en utilisant cette approche (les données sont injectées dans le processus de construction), cela génère un fichier BuildConfig qui a le jeton / secret en texte brut pour que tous puissent le voir après une simple décompilation.
Hrafn
-1

Eh bien, vous pouvez sécuriser votre jeton d'accès en suivant deux options.

  1. Utilisez enregistrez votre jeton d'accès dans le keystore Android qui ne serait pas inversé.
  2. Utilisez la fonction NDK avec un calcul qui enregistre votre jeton et NDK avec du code C ++ très difficile à inverser
M.Noman
la source