I have implemented synchronised keychain storage in my App with the SecKeychain API using kSecAttrSynchronizable. Am I correct in thinking that iCloud keychain must be enabled (iOS settings > iCloud > iCloud keychain) for this to work?
If so, is there any way to tell if this is enabled?
The kSecAttrSynchronizable attribute is used by your app to tell keychain if it is desired behavior that this keychain entry is synced to other Apple devices of that user or not.
Why would you desire an item not to be synced? E.g. the user doesn't want it to be synced as he wants to use a different password on his iPhone and on his iPad; so you may like to offer a pref and let the user chose if he desires syncing this password. Or syncing this password is simply not meaningful, e.g. it is a password that is used to encrypt local data of your application, local data that will only be present on the current device and thus this password is of no use to other devices, they lack the data for decryption.
However, your app can only express the wish for your item to be synced, whether syncing takes place at all is up to the user. The user decides if he wants password syncing at all, after all password syncing requires the passwords to be stored on Apple's servers. They are stored encrypted and not even Apple themselves have access to the password data, yet some users still don't have a good feeling having when that kind of information lying around on public servers on the Internet. So unless a user enables syncing, no passwords are synced.
Why would you need to know if the user has enabled it? To tell the user that passwords are not synced unless he enables syncing of passwords? Sounds a bit like telling the user that the room is dark, unless he turns on the light. If it is not on, the user may have chosen so on purpose, you cannot know if he did, can you? If you offer an option for password synchronization in the app prefs and the user enables is, just show an info text below that this feature requires iCloud keychain syncing to be enabled or else will have no effect.
Other than that, if you don't offer such an option, it should still be pretty obvious to all users that when your app promises "Now supporting iCloud Keychain Synchronization" that this feature will only work if "iCloud Keychain Synchronization" is enabled, don't you think? So to my best knowledge, there is no API that will directly tell you. One may detect in indirectly through other means but I don't recommend such kind of hacks, they are very fragile and sooner or later break with an update.
Related
I am migrating our organisation's app to a new developer account, for internal reasons. I've learned that upon transferring the app to the new account, and after we release an update for the app from the new developer account, we will incur a one time loss of keychain data.
My concern is, that we cannot afford this loss of data. Due to security reasons and nature of the type of clients using the app.
So my question is 2 part;
1) Is there any way that I can prevent this keychain data loss?
2) If not, what are the alternate strategies I can use to prevent the users from getting logged out during this transition?
Assuming you're talking about a real, full App Transfer I don't think this is possible. Keychains are not just differentiated via the app ID, but also the organization's ID (or more precisely the organization's ID is part of an app ID). Since the app's ID de facto changes with a transfer, iOS will prevent it to look up its old keychain. Not even app groups get around this, as a group cannot consist of apps by different organizations AFAIK. Apple would need to implement a kind of exception to this for at least a certain "migration period", but I doubt that will ever happen (for security considerations).
The only way to circumvent a re-login so that the transferred app can save the credentials in its "new" keychain would be to first have an update for the old, not-yet transferred app and have it save the credentials elsewhere, then have the transferred app look them up from there. I'd strongly recommend against this for security reasons, but if you absolutely must do that, you could upload the credentials somewhere secure (via an encrypted connection, obviously, i.e. SSL). You might even be able to use shared web credentials for this, but I haven't looked into that too deeply, so I am not sure whether both apps can be configured to be associated with that website (they're coming from two different teams, after all, but it might be allowed).
Even then, some users might "miss" the update of the older app before the transfer (and update to the "new" one), then they would have to re-login anyways.
If you follow this idea, be aware that you're "moving around" users' private data in a new way! Considering the recent GDPR fuzz this might even have string legal implications, so check with your company's legal advisors about this, too!
1) There is no way your can prevent data loss, since the App ID Prefix has changed during app transfer TN2311 > A one-time loss in keychain data will occur if you switch your App ID prefix
2)
If you application utilizes Push Notification, you can use the APNs device tokens to remap the user account.
Once the new app is launched:
Send the device token to server
Find the username from your database
Generate a session token (add your own security design here)
Save username + the token in your new Keychain
For those who doesn't allow notification, just force them to relogin
I'm writing my first app for iOS. In it conceived some protection from repetitive actions of the same user device (few, if apple account. Login "login-password" at the application level as such does not exist, therefore it was necessary to implement a hidden identification.
Convenient would it be to generate a random number that would be stored somewhere in the user, and remained unchanged even when reinstalling the app.
Started to read it. Learned about SSKeyChain. But just do not have enough experience to understand your logic... Please explain in accessible language!
My assumptions:
(please correct if I'm wrong!)
1) each user single Apple account that is attached all apps to one of the device, and thus the storage on the device. Or is the cloud for one account and multiple devices for this account (which is called keychain)?
2) has a free Access to the library SSKeyChain (via the security framework), which I for your application can write any data with their keys (the password to the app, login, color scheme)... so if you reinstall the app, it could check "are there any settings in KeyChain for me?" and take data from there. Similar to NSUserDefaults/SharedPreferences (ios/android), not receding after reinstalling the app.
3) the Possibility of losing data from KeyChain the user device is only shift Apple account any action by Apple.
So? :)
If you reinstall app,information stored in keychain is still there.But your provisioning profile should not change
From document
On iPhone, Keychain rights depend on the provisioning profile used to sign your application. Be sure to consistently use the same provisioning profile across different versions of your application.
Keychain is encrypted container and in iOS an application can access only its own keychain items.
When a user backs up iPhone data, the keychain data is backed up but the secrets in the keychain remain encrypted in the backup. The keychain password is not included in the backup. Therefore, passwords and other secrets stored in the keychain on the iPhone cannot be used by someone who gains access to an iPhone backup.
It is just an iOS provide container to save sensitive data。I do not understand what you say about Apple account.
Does apple support syncing Keychain across multiple installs of the same app under the same Apple ID?
I can find documentation about keyChain but is iCloud keychain available to developers? I cannot find any documentation for that.
Yes - The keychain is user tied though. The iCloud syncing is something the user can choose but you can't be sure this is turned on. Because it's user tied the user have to use the same Apple ID on all the devices and iCloud sync has to be turned on.
As far as I remember you can choose to share the keys you save with other apps made by the same developer.
Update to answer comment: Yes - This is seen as a safe way to store information. If I remember correctly the keychain is encrypted while not in use and can only be unlocked (automatically) by the Apple account. Just note that users will be able to see what is stored in their keychain so this is not a place to hide information from the user.
The keychain should be used to store password and other information that should be stored safely but not hidden from the user.
To contextualize the question, our use case is an app through which users can get free promotional items on signup. We would like to prevent abuse of the system by limiting to one promotion per device. Since we can't access the UDID, we need some other (mostly) reliable way to check if the phone has already signed up an account. We don't need a solution that is impossible to circumvent, just one that is highly inconvenient to circumvent.
If we store a unique key in the user's keychain, then we'll be able to read it again even if they uninstall and reinstall the app. We're considering using this method to track devices that have already signed up accounts.
Questions:
Is there a relatively easy way that the user could delete or change our app's keychain data? You can assume that the user's device is not jailbroken, and that they will not go to the trouble of completely reinstalling the OS.
What are other options besides using the keychain we might consider? Keep in mind that the app communicates with our server during signup, so we can store previous signup information of any kind on the server.
Are there any gotchas or problems with the keychain method we should know about?
I am working on an app that has a number of in app store purchase items that will enable certain functionality.
After each item is purchased, I would need to remember it (of course). I would also like to persist this information in iCloud in case the app is deleted or is installed on another device.
What is the best data structure to be used?
Can user defaults database be used for this?
What is important is that the user will not have access to change those values and enable by themselves the paid functionality.
Can user defaults database be used for this?
It can, but it's not the best idea to do so, since
What is important is that the user will not have access to change those values and enable by themselves the paid functionality.
and NSUserDefaults stores its contents as binary or plaintext property lists. Easily changeable on a jailbroken device. (Also changeable on a non-jailbroken one by modifying the iTunes backup files).
What you could do is either store them in the keychain, although the keychain is not really designed for this (and it can also be dumped on a jailbroken device using Ptoomey3's awesome Kaychain-Dumper tool), or better store it remotely on your server and let your server check what the user has purchased.
Of course, if it's not only the server that does the check, so for example you don't only send or don't send content based on purchases, but you also use this check for performing actions within your app, then it also can be hacked (google "MobileSubstrate cheat DoodleJump" for a nice example).
All in all: there's no perfectly secure system.
I use the KeychainItemWrapper class to store a flag in the keychain. The nice thing is, so far, is that the keychain survives an app deletion. IF the user then reinstalls the same app on the same device, the keychain data is still there.
There is no need to use iCloud. If the user installs your app on another device, you just need to provide a "Restore Purchases" button in your app. Then you call the Store Kit APIs to restore existing purchases. The "In-App Purchasing Programming Guide" covers how to do this.
This same functionality will allow a user to restore their purchases even if the flags in the keychain are lost.