Can device token of Push Notification be used as a unique identifier? - ios

Problem: using UDID is deprecated - we cannot use it anymore.
There are some solutions on the net: generate GUID and store it in the "safe place", iCloud, IdentifierForVendor starting with iOS6, OpenUID, SecuredID and so on...
Request:
I need to have a unique identifier of the Device to store user data on our server.
Question:
Can I use deviceToken of Push Notification as a unique identifier?
What are the pros and cons of this idea?
(-) user can disable push notifications
(+) unique number
(+) supported in all iOS

This is a terrible idea, the token can change if the user changes device or for some other unknown reason.
The user can have multiple devices
If the user reinstalls the app they can get an other token
It's not 100% that the user will keep the same token.
And most important of all: You are identifying devices not users!
One solution is to generate a UUID and save it in the user keychain where you retrieve it. But this can also be removed if the user clear the device.
You best option is to allow the user to login with an account, which that can create. Then you can combine this with the UUID in the keychain.

You should use identifierForVendor. The deviceToken for push notification is unique, but CAN change.

The token can change if the user reset the device, for unique device identifying you can use the following code
float currentVersion = 6.0;
NSString *udid = nil;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= currentVersion)
{
//below code is taken from the Apple Sample code, to check you can download the files
https://developer.apple.com/library/ios/releasenotes/StoreKit/IAP_ReceiptValidation
// OR
http://developer.apple.com/library/ios/releasenotes/StoreKit/IAP_ReceiptValidation/VerificationController.zip (line number 319)
udid = [UIDevice currentDevice].identifierForVendor.UUIDString;
}
else
{
//may cause apple rejection
udid = [UIDevice currentDevice].uniqueIdentifier;
//i think we can use the below link for ios5 or below but not sure it may accept or reject
https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5
}
//just saw a link which may help you better and have a look at image
http://www.doubleencore.com/2013/04/unique-identifiers/
can someone suggest the best way to persist the unique id even after reinstall app, delete app or system restart or system boot or factory reset

Related

Obtaining a Unique Device ID [duplicate]

I have used mac address to identify iOS devices in server side. When run my application with iOS 7 unable to retrieve the correct mac address. Alternately i used
NSUUID *oNSUUID = [[UIDevice currentDevice] identifierForVendor];
[strApplicationUUID setString:[oNSUUID UUIDString]];
property. But this value also changed after every new installation of application. Now i want detect particular device in server side? How can i get some unique id per device in iOS?
You can no longer get a unique ID per device. identifierForVendor is the best you're going to get. Apple has systematically disabled identifying a specific device so that users' IDs can't be passed around by marketers.
To get the identifier ID as a string, you can use
let deviceId = UIDevice.current.identifierForVendor?.uuidString
UPDATE
If you want a universal ID then you have the option to use advertisingIdentifier. However, if the user has limited ad tracking in their device settings then this value will simply return all zeroes.
import AdSupport
let identifierManager = ASIdentifierManager.shared()
if identifierManager.isAdvertisingTrackingEnabled {
let deviceId = identifierManager.advertisingIdentifier.uuidString
}
N.B. Apple recommends that this code only be used by companies building advertisement frameworks, rather than the app developers themselves. If you use this within your code for non-ad-related purposes then prepare to have your app rejected.
The best way to get the device id is identifierForVendor
UIDevice *device = [UIDevice currentDevice];
NSString *currentDeviceId = [[device identifierForVendor]UUIDString];
UPDATE
For Swift 4.1 use
UIDevice.current.identifierForVendor?.uuidString
Getting device ID in
Swift 3
let device_id = UIDevice.currentDevice().identifierForVendor?.UUIDString
Swift 4:
let device_id = UIDevice.current.identifierForVendor!.uuidString
Getting Device Id in Swift 3.x
let deviceId = UIDevice.current.identifierForVendor?.uuidString
You can use this lib: https://github.com/fabiocaccamo/FCUUID
Please look on the table in the Persistence section. uuidForDevice will cover the most of needed cases and it is the best replacement to udid from old versions of iOS.
Examples in Readme are in Objective-C but it works with Swift too. I have used it since Swift first release until now (Swift 4.1).
For Swift 5
let deviceId = UIDevice.current.identifierForVendor?.uuidString
You'll have to use UIDevice's identifierForVendor method like so:
let deviceId = UIDevice.current.identifierForVendor?.uuidString
But as explained here in great detail: https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor
the ID changes on every reinstall of the app (from AppStore).
One easy solution to circumvent this is to use the Keychain to store the deviceId once acquired. If the keychain item is not present - which will be the case for the first install* - acquire the deviceId as stated above and store it in the keychain.
*) This is iOS so there has to be some gotchas: If the device is reset or restored from backup, keychain items might disappear. So there's no 100% chance here, but since this scenario is quite unlikely, it's the best choice you've got.

Programmatically check whether or not application was previously installed by user

I want to check whether or not my application was previously installed on a particular device. Is there any programmatic way to do so?
You can use keychain. but when user reset his/her phone this value will be lost .
I think there is no option is available to such case except you have to use iAd in your app. apple provide unique id for that that will remain constant after reinstall application.
OPTION #1:
You can use NSUserDefaults or save the flag to keychain, in order to not lose it after app uninstall, and check in application:didFinishLaunchingWithOptions: method:
BOOL installFlag = get it from user defaults or keychain;
if (installFlag)
{
//App was installed
}
else
{
//This is the first install ever
installFlag = YES;
//Here save the YES value to user defaults or keychain
}
If you will save the flag to keychain, then use a Keychain Wrapper, like this
one.
The weak part of this option is that even if keeping the flag in keychain, the value could be lost, after reseting device settings, that's why I would prefer the following option:
OPTION #2:
Keep the flag remotely on a server database, as a key you can use device identifier:
NSString *uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
And you will have to check, if there is a record in your database with current device identifier, then app was already installed, if no then add the flag and the identifier to the database. (But you will need internet connection every time).
You can use keychain to keep log of your app previously installed or not.

Uniquely identify the device in iOS

I am developing a corporate application on the iPad for a certain business requirement.
This app is meant to use in a specific number of devices which is predefined by the admin.
But I also need the application to reject any login requests even if it is from an authorised user,when he or she is using a device which is not defined by the admin.
Edits:
Say I have 2 devices and I have my credentials to login to the app, And my need is, to restrict the login from the devices which is not mine.
For that I have to identify whether the login request is comes from my device or not.
Previously we could use device UDID to do this, but now it is deprecated.
Can any one please suggest a method to implement this ?
try this. for more info check UIDevice
// IOS 6+
NSString *uniqueIdentifier = [[NSString alloc] initWithString:[[[UIDevice currentDevice] identifierForVendor] UUIDString]];
You can use iCloud over here because UUID has been deprecated and vendorId is uniqe but might be change if you uninstall the app and install it agian,
So I would suggest iCloud will be safer, what you cna do is at the time of application launch you can generate one token which is unique and save it to your iCloud data storage along with user credentials,
So from the next time onwards when user will try to login you can check it with iCloud.
How about using Apple's enterprise distribution system? That will allow you to deploy the app to a corporation, and have tight access control.
https://developer.apple.com/programs/ios/enterprise/
Just Trick:
You can Implement APNS code to your Project and Get Device Token.
The Device Token is Unique One. But The user Must Allow the APNS.
Note: APNS Device Token is changed to Following reasons.
Change of Bundle id.
Change of Development Mode(Sandbox/Production)
I have implemented a solution for exactly your problem, The best solution (and Apples recommended route) is to create a UUID unique to your App like this:
NSString *uuidString = nil;
CFUUIDRef uuid = CFUUIDCreate(NULL);
if (uuid) {
uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));
CFRelease(uuid);
}
Then, and this is the key, you can store that to the iOS keychain (Handy classes here: https://github.com/lukef/IXKeychain) and values in the iOS keychain are NOT removed when the user uninstalls the App, so you can persist your own UUID through App installs which is a key part of managing a specific number of devices against a user account.
This method will return a string for every device. Since it is gonna change every time for single device
so we are storing it in a keychain and can refer it whenever we need it.
+ (NSString *) uniqueDeviceIdentifier
{
NSString *deviceUUID = [[SGKeyChain defaultKeyChain] stringForKey:#"uniqueId"];
if (!deviceUUID) {
if (!deviceUUID.length) {
NSString *deviceUUID = #"";
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
deviceUUID = [NSString stringWithFormat:#"%#",[NSString stringWithString:(__bridge_transfer NSString *)uuidStringRef]];
[[SGKeyChain defaultKeyChain] setObject:deviceUUID forKey:#"uniqueId" accessibleAttribute:kSecAttrAccessibleAlways];
}
}
return deviceUUID;
}
yo can refer to this repository... https://github.com/sgup77/SGKeyChainWrapper for SGKeyChain implementation
Ok I will share the approach that we follow for a B2B enterprise app.
.
Every User has login Id and Password.
1. So user register his device with Server using deviceReg API which takes clientDeviceId as param(client generated uuid) along with username and pass.
2. Server returns a server generated unique identifier to be used by application on that particular device.
Conclude - in this way you can restrict the user with a certain device.
You can use below method to generate deviceSpecific client UUID
- (NSString *)getUuid
{
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
NSString *uuid = [NSString stringWithString:(__bridge NSString *)uuidStringRef];
CFRelease(uuidStringRef);
return uuid;
}
Please note:
I remove the explanation about using AuthKey, AccessToken and others which we use for security purpose as you do not use any auth server.
I hope it helps.
Update 1.
Since you are having an enterprise application so i am sure you would be having atleast the user e-mail ids.
So the account manager should than 1st send a email with one time token to all active accounts.
This token can be requested by the application while registering the device and send to server for validation.
Also the server invalidates the token once used to avoid misuge.
There should be a migrAtion api which uses the server generated device id and a migration token if user migrates the device.

Unique Identifier should not change with iOS version change

I'm developing an application which is using device unique identifier to register device with server.
I am using MacAddress to get unique identifier of device, but in iOS7 it will return same(static for all device).
I found other alternate as
NSUUID *vendorId = [[UIDevice currentDevice] identifierForVendor];
But that will change as iOS device changed.
So can anyone suggest me some unique identifier which will not change if iOS version change it should be same for all iOS version (iOS7, iOS6).
There is a simple answer: It is not possible. Here you have an overview over the identifiers: The Developer’s Guide to Unique Identifiers
Apple is not allowing to use the Device's UDID to identify the users. So you can do it in other way.
Instead of sending the UDID to the server, create a unique Id on the server and put that ID in the application to recognize the user. In this way, you will not break the Apple's guidelines and the problem of varying the iOS versions also get resolved with this.
Just store the UUID into the keychain.
sskeychain refers to https://github.com/samsoffes/sskeychain
code as following^^
NSString *identifier = [SSKeychain passwordForService:kSSToolkitTestsServiceName account:kSSToolkitTestsAccountName];
if (identifier != nil && [identifier length] > 0) {
return identifier;
}
identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[SSKeychain setPassword:identifier forService:kSSToolkitTestsServiceName account:kSSToolkitTestsAccountName];
return identifier;
Unfortunately Apple disallows application to Uniquely identify a device (AS per them it violates User Privacy).. So you have either left with vendor ID or Advertisement ID.. another thing which you can try is that writing a web service which provides a unique ID to your app on first login and you will store that in in key chain or DB on your device..

CFUUIDCreate UUID changes constantly

I am a beginner iPhone app developer and I am trying to show the iPhone or App unique identifier on a label through an IBAction button. I researched a little and know that some of the code have been deprecated and CFUUID is used instead. The code below is what I used. However, every time I touch the IBAction button, the UUID changes. What am I doing wrong?
CFUUIDRef udid = CFUUIDCreate(NULL);
NSString *udidString = (NSString *) CFUUIDCreateString(NULL, udid);
uuid.text= udidString;
I think you have misunderstood the purpose of CFUUIDCreate(), Read its documentation you'll understand.
I guess the API is serving it's purpose properly, which is to create universally unique identifier means every time you call this it will return you back unique identifier randomly.
You can use
[[UIDevice currentDevice] uniqueIdentifier]
However, this method is depreciated. In order to get a unique identifier for each device, you can still use CFUUIDCreateString and save the output to user defaults. Load this value each time the app runs. If the app is deleted and then reinstalled this value will be different.
If you do need a unique identifier across app installs you can use the network MAC address.
As mentioned above, CFUUIDCreate is intended to create a different UUID each time it is run. You can create one, and store it in your app if you like, or you could try something like https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5 - basically, it provides a uniqueGlobalDeviceIdentifier function on the UIDevice, using an MD5 hash of the MAC address as its basis.
[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]

Resources