How to migrate KeyStore and Keychain key-value pairs generated by and old Cordova-based App to a new React Native based App? - react-native

The scenario is quite simple: there is an old App written using Cordova that has to be updated with a new App written from scratch using React Native.
I am not the developer and the maintainer of the App written using Cordova but I could put hands on its source code. I have to rewrite the App and to make a "silently" update, i.e. the new App must no "reset" the data stored on KeyStore (Android) and Keychain (iOS) and it must reuse these data.
When I "update" the App on my test devices I try to access the data generated by the old App using:
react-native-keychain
react-native-secure-key-store
and try to fetch the data, but with no success. The problem is the same on iOS and on Android.
Focussing for the moment on iOS, I use Xcode to build both the Apps. Firstly I build the old version of the App, generate the data and store them on Keychain. Then, I build the new App version, superseding the previous one. I have ensured that on Xcode the Bundle Identifier and the Signing Certificate is the same for both versions. But from the new version of the App I am still unable to access the Keychain. To make the litmus test: I downgrade the App re-building the old version another time, so the old app replaces the new one and in this case from the old App I am able to access the Keychain data.
I am suspecting that, even if the Bundle Identifier, the two Apps are using two different Keychain zones. So, what I have to do in order to be able to access the data stored by the old app from the new one?
The idea I that the user shouldn't be affected by the update of the App, so the Keychain (and the KeyStore) of the old app must be re-used by the new app.
Note: I see that on the old App, the function used to store data in Keychain/KeyStore is:
var ss = new cordova.plugins.SecureStorage(callback)
Note: I have already read this from Apple Developer website, but I suppose it could be not my case, because I can't set the Keychain sharing on the old App, since we are not permitted to release an update of the Cordova-base App. But, however we tried internally to use Sharing Access without success.

In iOS in particular, keychain access is not just tied to the Bundle ID and signing certificate for the app. There is a third element called the "Groups Entitlement" that is designed to allow multiple applications from the same vendor to share keychain access to the same data (imagine separate email and calendar apps sharing a user's login data). Documentation for this mechanism begins here:
https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps
The documentation is fairly dense, but despite being intended for multiple apps to share data this also controls an application reading its OWN data. You must ensure that your parameters match the old app precisely or you will not be able to read the old values. You didn't provide the code for the old or new apps, but as an example if the old app had stored values in the Keychain on iOS, you might use react-native-keychain and the following code to read it:
// The "access group" is the Team ID of the OLD APP followed by its full Bundle ID
const accessGroup = 'A12BC3D45.com.company.BundleId';
const accessOptions = {
accessGroup,
accessible: Keychain.ACCESSIBLE.AFTER_FIRST_UNLOCK,
};
const oldCreds = await Keychain.getGenericPassword();
console.debug('Found old credentials', oldCreds); // REMOVE AFTER DEBUGGING
react-native-keychain has several load functions and you may need to experiment with others (such as getInternetCredentials) if your old app stored things differently.

Related

Inconsistency when reading Appstore version to force update (React Native)

I have a mechanism reading the Appstore version and forcing the user to update the app. For doing this, I use the following URI: https://itunes.apple.com/lookup?bundleId=xxxxxx
It used to work, but with the last release of my app, I have noticed that it wasn't forcing the update anymore, despite the new version was on the store (the Update button was visible on the store page).
I decided to not update it and let the weekend pass, and today my app was already up-to-date when I opened it. I suppose my phone updated it automatically, unfortunately, so I cannot be sure that my app would have forced the user to do it, but I suppose so.
My guess is that the link I'm using in my app and whatever API iOS is using to automatically update, need time to know the latest version that is already available on the store.
Does anyone have any information about this?

Does redux-persist persist/save data in between App updates?

On my phone when I'm doing debugging...if I save something on redux-persist, then I change some code and save and run: npx react-native run-android...when the new version of the app loads I still can see the data I have saved previously.
Does this mean redux-presist is good as a database substitute so that even after App updates in the Appstore then the data saved will still be in the device and accessible by the updated App?
As far as I know it saves the store into AsyncStorage which uses the sandbox of your app which can be only accessed by your app (app id and only that id can access that sandbox) no matter which version. It is different, I would not consider it as a substitute but rather as a supplement to a data base. That doesn't mean that you can't try to use it as such.

Access `Titanium.App.Properties` in native app

TLDR: Is there is any native way to access the Titanium.App.Properties for both Android and iOS?
I am working on a project where the original app was made with Titanium, and the new updated version is built with Xamarin.
The original developers thought it would be smart to save a Device Token in the Titanium.App.Properties that would be used to access all the users history and purchases.
The device token is not stored anywhere else, so the only way to get to it is through Titanium.App.Properties.
I have the key they used to store the token. So my question is, is there is any native way to access the Titanium.App.Properties for both Android and iOS?
From this doc there is a paragraph:
"Both iOS and Android store app properties in special files on the filesystem. Natively, iOS properties are known as NSUserDefaults, which are stored in .plist files in the application's library directory. Android stores them in standard xml text files at /data/data/com.domainname.appname/shared_prefs/titanium.xml. Titanium provides a uniform means to set and get app properties via the Titanium.App.Properties API."
From this SO question it sounds like a module needs to be used:
"Other iOS applications cannot access these properties and native Android modules must use the Titanium module API TiApplication.getAppProperties method to access these properties."
For Android the Titanium properties are stored in the shared preferences with the path titanium.
ISharedPreferences TitaniumSharedPreferences = CrossCurrentActivity.Current.Activity.GetSharedPreferences("titanium", Android.Content.FileCreationMode.Private);
Then simply use the shared preference to get any property you need.
var userToken = TitaniumSharedPreferences.GetString("UserToken", string.Empty);
For iOS it is simpler, it just uses the NSUserDefaults.
var userToken = NSUserDefaults.StandardUserDefaults.StringForKey("UserToken");
For Android the TiProperties.java file says:
Instantiates the private SharedPreferences collection with the given
name and context.
This means no other Android application will have
access to they keys and values.
You say you use the token to get a history. Is that coming from a server? So is the token send to the server to do the request?
On the other hand: do you own the source code of the Ti app? Create an update that will store the token in some other way.

Why new WQA app builds are not identified in the bug, feedback and session details?

Recently some updates were made into an iOS app build within WQA and new builds were distributed successfully. It is expected to have new/updated build version of the app in the collected data, however, new app build versions are not captured in WQA bug, feedback and session details.
In iOS the "CFUUIDCreate" method is used to generate a Universally Unique Identifier (UUID). When the back-end detects that this has changed, it checks automatically creates a new version for the application. Small UI changes might not generate a new UUID.
See the following tech note for more information:
http://www-01.ibm.com/support/docview.wss?uid=swg21679495

Are there any update frameworks for iOS apps?

I need to be able to update my app from within the app itself. I know Sparkle works for Mac Apps but I can't seem to find any for iOS.
Edit: I am not asking how to bypass the review process. I was thinking that there might be frameworks similar to Clutch.io that allow updates to images/documents/etc from within the app. Or things like UrbanAirship that manage in app purchase data that allows an app to be extended from the app itself.
You can't replace your app with an updated one (except through the App Store) and you can't replace parts of your app with updated parts (that would make your app's code signature invalid); you can only update stuff that's outside of your app's bundle.
You can't update the app binary yourself, the system is responsible for updating all apps.
Though, if you just want to update some data in your app you can do that for sure.
Here is what I was looking for:
http://code.google.com/p/cooliris-toolkit/
It has a class called RemoteUpdater which allows me to download zip files of images/data or whatever I like to extend my content.
Depends on your needs. If you dont want to see the app you can also do an Enterprise Deploy.
Used by corporations to distribute apps to their clients or employees.
Needs a separate Apple account which costs more.
Uses same process as deploy to appstore
Archive > Distribute > create ipa/plist > copy these to webserver with html page with link to plist and user clicks on link from Safari on iOS Device and it installs.
Going back to CArpp Store review process after that is painful.