0

This is my logic for implementing one device and one credential for my iOS Application according to the Client Demand

LOGIC

I am developing an iOS app which calls web-service for login and at that time i send login credentials to web server along with vendor identifier (identifierForVendor),to identify device uniquely for those credentials.So user can have only one device and one credential.

This identifier will then store in database of web server and also in device database.Next time when user opens application and will try to download data from web server firstly local identifierForVendor on users device will compare with identifier stored on web server.

CONCERN

I have a concern about whether the identifierForVendor will change or not if I download the application from Appstore and reinstall again from the Appstore by deleting the application?

This is the following scenario:

  1. Downloaded an App named “ABCDApp” from AppStore . Logged in with my credentials . I got an identifierForVendor for example: “1234”

  2. I deleted the app from my phone and again reinstalled the same app from AppStore Will I get the same vendor Id “ 1234 “ ? Or I will get different vendor Id if I reinstalled again from AppStore? Please note this vendor has only single App and no other App

I have from several links that it is not going to change if I UPDATE THE APP from the APPSTORE. The link which is follow is : Vendor ID does not changes when Updating app from Appstore. But what about reinstalling case ?

This is the code :

NSString *uuid = [[UIDevice currentDevice] identifierForVendor].UUIDString

My concern is : What if I uninstall and reinstall the application from Appstore again? Will it change ? If it changes how can I handle one device, one credential logic which I am planning to implement for my Application?

user16780334
  • 422
  • 5
  • 20

2 Answers2

2

From the documentation:

The value changes when the user deletes all of that vendor’s apps from the device and subsequently reinstalls one or more of them.

So unless the user has another app from the same vendor installed, this id will change after deleting and reinstalling. In your case, where there is no other app by the same vendor, this means that the ID will change, and is therefore probably unsuited for your situation.

One alternative could be to store a locally created UUID in the keychain, since keychain entries currently survive deletion and reinstallation of apps. However, this is an undocumented (mis)feature and may break at any time.

Gereon
  • 17,258
  • 4
  • 42
  • 73
  • Thanks .. As of now my vendor has a single app which is developed by me . So will it change even if I uninstall and reinstall from Appstore? If yes, how can I prevent my logic from breaking when reinstalling happens? Can you please add that too in answer – user16780334 Jan 09 '21 at 07:31
  • Yes, in this case the id will change. This means that identifierForVendor is probably unsuited for you. – Gereon Jan 09 '21 at 07:37
  • Thanks for an answer can you please tell will it work if I store the identifierForVendor in the Keychain as you suggested instead of creating custom UUID? Can you please elaborate the answer with the code of Custom UUID creation please and if possible storing/retreiving from keychain? – user16780334 Jan 09 '21 at 07:40
  • 1
    identifierForVendor _is_ a UUID, so you should be able to use it, but `NSUUID` exists and is trivial to use. As for storage, see eg. https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_keychain?language=objc – Gereon Jan 09 '21 at 07:45
  • Since you have a pretty good experience in leading mobile application can you please suggest the best approach that you are following for One device, One credential scenario? I am still a beginner so any idea/Help will be appreciated – user16780334 Jan 09 '21 at 07:47
  • @polina related to the keychain persistence thing: Some iOS 10.3 beta releases broke this behavior, although official release not. (see [this](https://stackoverflow.com/questions/18911434/will-items-in-ios-keychain-survive-app-uninstall-and-reinstall) question and [this](https://developer.apple.com/forums/thread/72271) post in Apple Developer Forums) – gcharita Jan 09 '21 at 11:00
  • @gcharita so what you prefer when implementing one device one credential approach? – user16780334 Jan 09 '21 at 11:05
  • @polina as Gereon mentioned, there is no reliable way to do that. Based on [Apple's comments](https://developer.apple.com/forums/thread/36442?answerId=281900022#281900022), we shouldn't use that kind of authentication due to user privacy. [DeviceCheck](https://developer.apple.com/documentation/devicecheck/accessing_and_modifying_per-device_data) framework is documented (iOS 11+) but of course, it provides only a way to store a 2 bit state per device. – gcharita Jan 09 '21 at 11:24
2

Yes it changes all the time for each and every installation. If you want to send same UUID to service all the time you have save the UUID in KeyChainStore provided the link below: enter link description here

I have solved this problem with the help of the link provided above like this.

      NSString* identifier;
         UICKeyChainStore *keychainStore = [UICKeyChainStore keyChainStore];
        if(keychainStore[@"UDID"])
        {
            identifier=keychainStore[@"UDID"];
             NSLog(@"output is : %@", identifier);
             [SessionManager saveUDID:identifier];
        }
        else
        {
            identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; // IOS 6+
             NSLog(@"output is : %@", identifier);
             keychainStore[@"UDID"] = identifier;
             [SessionManager saveUDID:identifier];
        }
      
        +(void)saveUDID:(NSString*)udid
    {
        [[NSUserDefaults standardUserDefaults] setObject:udid forKey:@"UDID"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    +(NSString*)getUDID
    {
        NSString *udid = [[NSUserDefaults standardUserDefaults]
                           stringForKey:@"UDID"];
        return udid;
        
    }
   // logout from app
-(void)logOutFromApp
{

    UIApplication*app=[UIApplication sharedApplication];
              NSDictionary*dic;
    AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
    [appDel application:app didFinishLaunchingWithOptions:dic];
    [self.delegate logoutFired];
    
}

I hope it will help you. Happy Coding.

Mahboob Nur
  • 739
  • 2
  • 9
  • 34
  • 1
    what is the "SessionManager" here? – user16780334 Jan 09 '21 at 10:36
  • SessionManager is a class deals with saving and getting data in session using NSUserDefaults. +(void)saveUDID:(NSString*)udid { [[NSUserDefaults standardUserDefaults] setObject:udid forKey:@"UDID"]; [[NSUserDefaults standardUserDefaults] synchronize]; } +(NSString*)getUDID { NSString *udid = [[NSUserDefaults standardUserDefaults] stringForKey:@"UDID"]; return udid; } @polina – Mahboob Nur Jan 09 '21 at 10:39
  • Thanks Mahboob... Are you following the same approach for one device one credential as I am planning to do? – user16780334 Jan 09 '21 at 10:51
  • 1
    Thanks . So all I have to do is use the same code which you posted in answer and import UICKeyChainStore. What are you doing if the user plans to login from another device? Are you showing some alert like "You are already registered in another device. If you want to continue , please press yes" and on pressing yes you are clearing the session of previous device? – user16780334 Jan 09 '21 at 11:09
  • 1
    It is dealed in the server side. When user login with new device it automatically locks the instance of the previous device. According to the service response you can show alert "You are already registered in another device. If you want to continue , please press yes" I used the code in AppDelegate didFinishLaunchingWithOptions method. So it will be autoupdated in the session. No need to clear. @polina – Mahboob Nur Jan 09 '21 at 11:15
  • 1
    Sorry mahboob what do you mean by "locks the instance of the previous device". I mean if the server locks how will I handle in my previous device. I mean how can I make it logout application from my previous device? @MehboobiOSDeveloper – user16780334 Jan 09 '21 at 11:24
  • 1
    @polina for example You get a response from service "Already LoggedIn" then u can logout the previous device. If u get a response from serice "New Login" then u can proceed with new login. – Mahboob Nur Jan 09 '21 at 11:49
  • 1
    @mehboob thanks for the answer but I am still confused about how to logout from previous device if I log in with new device? For example I logged in device A and I reached Home Screen. now I took device B and logged in my app by pressing yes in the alert . So when I take device A which is showing Home Screen of my app, here I want that it must automatically logout since I am already logged in new device B. Should I call any API in my previous Device A to logout? how to automatically logout from Device A when I log in new Device B? – user16780334 Jan 09 '21 at 12:01
  • After u login with device B server will recognize your new device after that when u login with device A server will let u know that it is the old device then u will call this method I hope your problem will be solved @polina -(void)logOutFromApp { UIApplication*app=[UIApplication sharedApplication]; NSDictionary*dic; AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate; [appDel application:app didFinishLaunchingWithOptions:dic]; [self.delegate logoutFired]; } – Mahboob Nur Jan 10 '21 at 05:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227103/discussion-between-mahboobiosdeveloper-and-polina). – Mahboob Nur Jan 10 '21 at 06:25
  • Thanks mahboob... can you tell please from where I have to call this logout code? Because as I said the app in Device A is already logged in and is in Home Screen. So from where I have to fire this logout code? I want that code to be automatically fired. And what is [self.delegate logoutFired]; logoutFired method? so how home screen or any other screen will know that the app is already logged in new device and so it must logout from Device A. any way to autologout? – user16780334 Jan 12 '21 at 15:00
  • 1
    @polina when u get the response from service that your device is the old one.You can show alert and when user click ok you can call logout method for ok button click. It will work as autologout as well. – Mahboob Nur Jan 13 '21 at 04:04
  • Understood mahboob but my doubt is for getting response from service we must call service right ? Like any button Action etc ? How to handle this ? – user16780334 Jan 13 '21 at 06:54
  • Yes u need to call service api. @polina Service will detect and response the app then u can do the rest. – Mahboob Nur Jan 13 '21 at 07:19