Best way to store license key persistently on i-device - ios

I have a woocommerce store with a plugin which generates license keys.
The idea is that the user of my app, will enter a license key which will be checked against a server. If it is correct then the app will create a special file/persistent flag some how.
Once activated, the user can reset the device or whatever and the app will simply check to see if this persistent file/flag is there.
My questions are:
Is there a library available specifically for this sort of thing?
If not, what is the best/standard way of doing this so the file can't be copied to another device to fake an activation?
Could I use something untouchable inside the application bundle that isn't a file to do this?
Thanks guys, some guidance or suggestions would be great.

The "standard" way to do it is to have Apple manage the licensing for you via in-app purchasing or subscriptions, they provide a secure implementation for checking if something is paid for, but this may not be an option for you.
If you need to roll it yourself, you need to use assymetric encryption, with a private key on a server that nobody can access (except you) and a public key distributed in the app. You also need the [UIDevice currentDevice].identifierForVendor.UUIDString value on the device, which is a value unique to that device which cannot be changed by the user (unless they jail break).
The server encrypts some data like 2014-03-23,purchased-three-month-license,<device-identifier-for-vendor>,<long-random-number> and gives the encrypted data to the device as the license key.
The device has the public key, and uses it to decrypt the license key. Then it checks the result to see if the date is in the last three months, the device identifier matches the device's actual identifier, and verifies that the long random number is there and at least 10 digits or something (it doesn't matter what the random number is, it just needs to be there).
Anybody who jail breaks their device will still be able to bypass your security. There is no way to prevent this. But it will take the user a lot of work, they'll probably just pay instead.
All the libraries you need for the encryption are built in, but they're low level APIs and a bit complicated to use and it's easy to screw it up. I recommend RNCryptor as a high level wrapper around them.
Also note that if the user uninstalls your app, then re-installs it (or sometimes when Xcode installs a new build) the identifierForVendor will change to a new value. Apple enforces this to protect user privacy, there's no way around it. You will need to have the server re-generate a new license key based on the new identifier... perhaps by asking the user to enter an email address and password. You can prevent piracy by monitoring how many times a particular email address is used. If they generate license keys 5 times in 30 days, then you could flag them as a pirate.
Whatever license key the "woocommerce store plugin" is generating will not work, because it won't be using [UIDevice currentDevice].identifierForVendor.UUIDString as part of the license key generation. Without that value, it's going to be trivial for anybody to pirate your software.
There is no such thing as "something untouchable inside the application bundle". The only such thing is the Secure Enclave in Apple's hardware. And to protect user privacy app developers are not allowed to use it directly. identifierForVendor is the only option.
In older versions of iOS there were more options, but they were abused by advertising companies tracking Apple's customers, and so one by one Apple has blocked access over the years.

Related

Preserving Keychain data during developer account migration

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

iOS device specific unique identifier

Is there any way to generate unique id for IOS devices?
I have a framework that helps to the apps to take login token from it, I am using identifierForVendor with no problems because all consumer apps published from same vendor, but I want to add another one from different publisher and adding that app to chain, identifierForVendor is no work anymore,
Also I can't use keychain since they are using different team id,
So can you please let me know if there is any other way to do this?
If I'm not mistaken Apple has revoked access to the real device identifier (UDID) and rather provides a pseudo-identifier to limit malicious usage thereof.
Refer to this previous answer https://stackoverflow.com/a/19402414/28305.
UDID is not available anymore so you can use
UIDevice.currentDevice().identifierForVendor?.UUIDString
more here
Or you can use DeviceCheck framework that is available from iOS 11
Just create a new key in Apple Developer account and generate a token with
DCDevice.current.generateToken(completionHandler:)
Note: You must use only real device to receive token.
You can find good tutorial here
Short answer: no because of data privacy concerns (at least in the official statements).
Apple blocked access to 'identifiers' such as UDIDs and hardware data such as MAC addresses and others. Even if there is currently such as field, as soon as it's exploited by a certain amount of people it will be removed or obfuscated soon.
The only thing that might work for a while is trying to get a browser fingerprint of the current device.

How to get unique and consistent device id on Apple device

I need to generate a device ID that complies the following criteria:
It is universally unique.
It is consistent (as much as possible), i.e. it stays the same for the same device.
It requires minimal permissions.
It is legal to be transferred and stored.
The solution, for example, could be a hardware ID which is accessible with no special permissions which is then hashed and sent over the wire, I just don't know if there is any.
P.S. I don't want to store anything in the keychain or anywhere else. Just generate on the fly, and remain the same, independently from the app it's being generated on. And resetting it during factory reset or other rare occasions is fine.
While I could access some device specific token in the past, this is not possible any longer.
The API will serve you with a unique identifier for the app installation on that particular device. It seems storing that token and sharing it using the keychain (if not already present from another app) seems to be your best bet at the moment.
This is a necessity to protect users' privacy, and I strongly suggest not to work against that and compromise the concept (and I think it's prohibited in any AppStore app anyway).

Access iOS contact list without permission or asking - Privacy matters

I do know how to ask permission for contact's list accessing, is a very simple implementation, also I know Apple checks all this in case of going live to the App Store.
I'm about to receive a AdHoc bundle to a third party client, very very picky with privacy issues and I want to be certain that you cannot in any possible way in iOS7 access to the the address book, without previous and clear authorisation, nor storing some file in local or sending it through a web-service.
If there's other sensitive information than a programmer can access without the operating system firewall please let me know as well.
I read some subroutines can go through...
QUESTION: Can a developer access to the addressbook or personal information, directly or indirectly using a third party API or subroutine to the personal data, without explicit permission? Is an AdHoc bundle as secure as an AppStore reviewed App in that case?
Please do not punish me with negative feedback if you are not interested in privacy issues or think was that obvious, actually Apple's documentation is not clear and is focused on AppStore, mostly.
Thanks!
This answer came up in every search I did trying to find, CNContactPickerViewController, so I figured I should respond for posterity.
In iOS 9 and later you can call CNContactPickerViewController to present a system controlled contact picker that doesn't require permission to access the user's contacts. You can't hoover up all their contacts, which is what the original question implied (and is super creepy), but at least you can prompt the user to select a contact (or multiple contacts), which is sufficient for many legitimate use-cases.
Docs
The Address Book cannot be accessed without permission. No third-party API can get in, because internally, these API's need to go through the same permission checks as you need to. No app can get into a user's address book without the user's permission.
This is because of a security issue that Path, and some other apps, uploaded its users' address books to their own servers to use for whatever reason. To read more about it, look here
After this surfaced, Apple required the user's permission to access the user's contacts. Apple's iOS platform is possibly the most secure operating systems today, and there are few security holes that exist in their API's (minus the goto fail; mess-up).
App Store reviewed apps are more secure for the user than Ad-Hoc apps. The developers at Apple make sure that you do not do anything malicious with the user's contacts. In Ad-Hoc apps, there is no checkup. So, if you wanted to do anything dirty with their contacts in an Ad-Hoc app, you technically could (if the user gives you permission at all). You do not need to state what you will be doing with the permission, and so you are able to take advantage of the user's trust in you.
If you want the company to trust the app, suggest that they look it over with their own reviewers. If they don't think you are doing anything fishy, you are good.

iPhone app consumables - Server vs keychain method

I had an iPhone app developed by a company, which contains consumables purchases, specifically a currency named as "coins", used for app-specific purchases. In the current version, the team has added the ability for a user to register under a username/email/password. This information is stored on my external server and used as a recovery for the user's purchased coins via signing in using these credentials.
The model looks fine programmatically but is not convenient in terms of usability. Ideally, i would want my users to not have to register at all. I have been reading that it is a possibility to store the user's purchased consumables on the client side, using the internal keychain.
Now this would imply that consumables can only be restored on this single device (i guess unless iCloud is used). But is this allowed by Apple ? Or there should be a method to restore across different devices ?
If the keychain method is allowed, I believe that it would be way better for my app to go with that. I just wanted to make sure that Apple would not have a problem with that. I have been reading that it's allowed, but do not want to have unpleasant surprised after changing the whole client-server model to client-only keychain.
If you have experience with that, could you please let me know what the case is ?
EDIT : Somewhere on SO I read that using Gamecenter's GKPlayer class is also a way to store information on my server and retrieve that automatically in order to identify a user purchase. This would mean that the step of username/email registration is avoided, which is something i really really want to avoid. Is this really a possibility that is allowed by Apple ?
EDIT 2 : I am now thinking that I will keep the client-server model but lose the username/password and use the device id instead. This way i will be able to keep the restoration of coins working on a specific device. Would that be ok you think?

Resources