Save sensitive data in React Native

前端 未结 4 2100
日久生厌
日久生厌 2020-11-28 19:56

I am building a React Native application and I need to save some sensitive data like a token and a refresh token. The obvious solution is to save that information using Asyn

相关标签:
4条回答
  • 2020-11-28 20:17

    Just digging into the React Native code, I found the answer.

    Android

    The React Native AsyncStoragemodule implementation is based on SQLiteOpenHelper. The package where all the data classes are handled: https://github.com/facebook/react-native/tree/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage

    The class with the instructions to create the database: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage/ReactDatabaseSupplier.java

    By the Android documentation, the databases created by the application are saved in private disk space that's associated application, so it is secure.

    Just like files that you save on the device's internal storage, Android stores your database in private disk space that's associated application. Your data is secure, because by default this area is not accessible to other applications.

    Source

    iOS

    In iOS the AsyncStorage values are saved in serialized dictionary files. Those files are saved in the application NSDocumentDirectory. In iOS all applications live in their own sandbox, so all files of one application are secured, they cannot be accessed by the other applications.

    The code in iOS that handles the AsyncStorage module can be found here: https://github.com/facebook/react-native/blob/master/React/Modules/RCTAsyncLocalStorage.m

    And as we can see here the files used to store the values saved by the AsyncStorage are saved under the NSDocumentDirectory (inside the application sandbox environment).

    Every App Is an Island An iOS app’s interactions with the file system are limited mostly to the directories inside the app’s sandbox. During installation of a new app, the installer creates a number of containers for the app. Each container has a specific role. The bundle container holds the app’s bundle, whereas the data container holds data for both the application and the user. The data container is further divided into a number of directories that the app can use to sort and organize its data. The app may also request access to additional containers—for example, the iCloud container—at runtime.

    Source

    Conclusion

    It is safe to use AsyncStorage to save user tokens, since they are saved under a secure context.

    Please note that this is only true for Android devices without root and for iOS devices without jailbreak. Please also note that if the attacker has physical access to the device and the device is not protected. He can connect the device to the mac laptop and extract the documents directory and see all the contents saved under the documents directory.

    0 讨论(0)
  • 2020-11-28 20:21

    If someone wants the additional step of having the data encrypted, you might want to look at this: https://github.com/oblador/react-native-keychain

    It uses facebook conceal internally.

    0 讨论(0)
  • 2020-11-28 20:22

    AsyncStorage saves key-value pairs as a plaintext JSON file in the Documents directory. It does not encrypt its contents.

    This is a security issue (at least on iOS) because it's possible for an attacker with access to the device to obtain a dump of the contents of the sandbox and trivially extract any data saved through AsyncStorage.

    This used to not be clearly stated in the docs for AsyncStorage.js, but it is now: https://github.com/facebook/react-native/pull/8809

    Also see: https://stackoverflow.com/a/38398114/1072846

    0 讨论(0)
  • 2020-11-28 20:25

    I really recommand you to use a library like react-native-keychain to store private data in react-native

    For Android API level:

    • 16-22 use Facebook Conceal
    • 23+ use Android Keystore

    You can use it like that:

    // Generic Password, service argument optional
    Keychain
      .setGenericPassword(username, password)
      .then(function() {
        console.log('Credentials saved successfully!');
      });
    
    // service argument optional
    Keychain
      .getGenericPassword()
      .then(function(credentials) {
        console.log('Credentials successfully loaded for user ' + credentials.username);
      }).catch(function(error) {
        console.log('Keychain couldn\'t be accessed! Maybe no value set?', error);
      });
    
    0 讨论(0)
提交回复
热议问题