Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniquely identifying an iOS user

I'd like to create a user account on the server for new users of an app, but I'd also like to not ask the user to type in anything. Ideally, I'd like this to be automatic, like with Game Center.

But I'm wondering if it's possible. Is there anything I can use to uniquely identify the user? It's highly unlikely that I can find out the user's Apple ID. Also, the device ID uniquely identifies the device, not the user, so it would be useless if the user has more devices...

Is there anything else I can use?

About privacy - I don't want to find out anything behind the user's back. I have absolutely no problem with asking the user for access to their information (and if there is an API that grants me this information, it would be great if the API asks this itself). As Steve Jobs himself said, this is what privacy is all about - forcing apps to ask the user for permission before doing anything with their private data.

like image 941
rid Avatar asked Jul 22 '12 01:07

rid


People also ask

How do I know which iOS device is unique?

UDID(Unique Device Identifier) − A sequence of 40 hexadecimal characters that uniquely identify an iOS device. Since from iOS 5, Apple has deprecated the UIDevice unique identifier, that means the traditional way of getting the unique id.

Is iOS UUID unique?

UUID (Universally Unique Identifier): A sequence of 128 bits that can guarantee uniqueness across space and time, defined by RFC 4122. UDID (Unique Device Identifier): A sequence of 40 hexadecimal characters that uniquely identify an iOS device (the device's Social Security Number, if you will).

How can you identify a uniquely device?

UUID. randomUUID() method generates an unique identifier for a specific installation. You have just to store that value and your user will be identified at the next launch of your application. If you only target smartphones, you can take profit of the fact that the device have telephony services.

How do I find my UUID for iOS?

How to Find Your iPhone and iPad's UUID. Connect your iPhone or iPad to your computer, and then open iTunes. Click the device icon at the top. Your device's UUID is hidden by default—click “Serial Number” and it will change to display your UUID.


2 Answers

The correct solution is to use the iCloud Key-Value Store, where you can store a unique user ID without requiring any kind of authentication or user information such as an email address.

The end result is a random UUID (nothing that actually IDENTIFIES the user), that is different for each user, but will persist across multiple devices registered to the same iCloud account.

We define a field in our iCloud KV Store, let's call it userID. When the app is launched, we first check the userID. If it's there, then we're all set with our user's unique ID. If not, then this is the first time we're running for this user. We generate a random UUID and store it in the KV Store under userID. That's all there is to it.

Our experience shows that this UUID is unique per iTunes account. If your end-users are using family sharing, those accounts will be assigned different UUIDs (which may or may not be desirable but there's nothing you can do about it). Any number of devices launching under the same iTunes account will see the same UUID.

This approach is totally legit and should be approved by Apple with no issues.

Obviously you must enable iCloud Key-Value store on Xcode under Capabilities, just turn on the iCloud Switch.

Here's a simple class that implements this concept in Objective-C:

@implementation EEUserID  + (NSUUID *) getUUID {     NSUUID *uuid = nil;     NSString *uuidString = [[NSUbiquitousKeyValueStore defaultStore] stringForKey: @"EEUserID"];     if (uuidString == nil)     {         // This is our first launch for this iTunes account, so we generate random UUID and store it in iCloud:         uuid = [NSUUID UUID];         [[NSUbiquitousKeyValueStore defaultStore] setString: uuid.UUIDString forKey: @"EEUserID"];         [[NSUbiquitousKeyValueStore defaultStore] synchronize];     }     else     {         uuid = [[NSUUID alloc] initWithUUIDString: uuidString];     }          return uuid; }  + (NSString *) getUUIDString {     NSUUID *uuid = [self getUUID];     if (uuid != nil)         return uuid.UUIDString;     else         return nil; }  + (void) load {     // get changes that might have happened while this     // instance of your app wasn't running     [[NSUbiquitousKeyValueStore defaultStore] synchronize]; }  @end 

And for the header file:

#import <Foundation/Foundation.h>  @interface EEUserID : NSObject  + (NSUUID *) getUUID; + (NSString *) getUUIDString;  @end 

To use, all you have to do is invoke:

NSString *uniqueIDForiTunesAccount = [EEUserID getUUIDString]; 

Enjoy.

like image 58
ldoogy Avatar answered Sep 23 '22 09:09

ldoogy


Generate a UUID with this:

NSString *UUID() {     CFUUIDRef cfuuid = CFUUIDCreate(NULL);      NSString *uuid =  (__bridge_transfer NSString *)CFUUIDCreateString(NULL, cfuuid);      CFRelease(cfuuid);     return uuid; } 

Nothing here is deprecated or frowned on by Apple -- in fact, it is the way they suggest you do it. Store the generated UUID in the keychain and it will be there -- even if the user uninstalls and reinstalls your app. The UUID is unique for the device and the time it was generated.

You can then use various schemes to have the user group their devices together -- iCloud, or some sort of key that you deliver from the server.

Good luck!

Addition:

Here's how I store it in the keychain, using the uuid as a username and generating a random password:

uuid = UUID(); [keychainItemWrapper setObject:uuid forKey:(__bridge_transfer id)kSecAttrAccount]; NSString *pass_token = randomString(10); [keychainItemWrapper setObject:pass_token forKey:(__bridge_transfer id)kSecValueData]; 

Note that all of this can be done without any input from the user.

Update:

MCSMKeychainItem has a great solution to UUID generation and storage with [MCSMApplicationUUIDKeychainItem applicationUUID]. The library also has [MCSMGenericKeychainItem genericKeychainItemWithService:service username:username password:password]. Together, these functions take care of everything mentioned above. Easy to install with CocoaPods too.

like image 42
Erik Avatar answered Sep 22 '22 09:09

Erik