Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete keychain items when an app is uninstalled

I am using idandersen's scifihifi-iphone code for keychain and save password using

[SFHFKeychainUtils storeUsername:@"User" andPassword:@"123"
              forServiceName:@"TestService" updateExisting:YES error:&error];

When I delete the application from the device, the password remains in the keychain.

I want to remove the password from the keychain when the user deletes the application from the device. How can I do this?

like image 875
enc Avatar asked Jan 20 '11 12:01

enc


People also ask

How do I delete data from my iPhone keychain?

Click Finder > Go > Utilities > Keychain Access. 2) In Keychain Access, select the Passwords category on the left to review the list of sites and services for which you've saved a password. 3) Right-click the service you want to edit/remove, then left-click Delete.


8 Answers

You can take advantage of the fact that NSUserDefaults are cleared by uninstallation of an app. For example:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //Clear keychain on first run in case of reinstallation
    if (![[NSUserDefaults standardUserDefaults] objectForKey:@"FirstRun"]) {
        // Delete values from keychain here
        [[NSUserDefaults standardUserDefaults] setValue:@"1strun" forKey:@"FirstRun"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }

    //...Other stuff that usually happens in didFinishLaunching
}

This checks for and sets a "FirstRun" key/value in NSUserDefaults on the first run of your app if it's not already set. There's a comment where you should put code to delete values from the keychain. Synchronize can be called to make sure the "FirstRun" key/value is immediately persisted in case the user kills the app manually before the system persists it.

like image 187
Amro Avatar answered Sep 16 '22 13:09

Amro


For users looking for a Swift 3.0 version of @amro's answer:

let userDefaults = UserDefaults.standard

if !userDefaults.bool(forKey: "hasRunBefore") {
     // Remove Keychain items here

     // Update the flag indicator
     userDefaults.set(true, forKey: "hasRunBefore")
}

*note that synchronize() function is deprecated

like image 36
bwc Avatar answered Sep 18 '22 13:09

bwc


There is no trigger to perform code when the app is deleted from the device. Access to the keychain is dependant on the provisioning profile that is used to sign the application. Therefore no other applications would be able to access this information in the keychain.

It does not help with you aim to remove the password in the keychain when the user deletes application from the device but it should give you some comfort that the password is not accessible (only from a re-install of the original application).

like image 31
Shane Fitzgibbon Avatar answered Sep 20 '22 13:09

Shane Fitzgibbon


For those looking for a Swift version of @amro's answer:

    let userDefaults = NSUserDefaults.standardUserDefaults()

    if userDefaults.boolForKey("hasRunBefore") == false {

        // remove keychain items here


        // update the flag indicator
        userDefaults.setBool(true, forKey: "hasRunBefore")
        userDefaults.synchronize() // forces the app to update the NSUserDefaults

        return
    }
like image 44
rsc Avatar answered Sep 18 '22 13:09

rsc


C# Xamarin version

    const string FIRST_RUN = "hasRunBefore";
    var userDefaults = NSUserDefaults.StandardUserDefaults;
    if (!userDefaults.BoolForKey(FIRST_RUN))
    {
        //TODO: remove keychain items
        userDefaults.SetBool(true, FIRST_RUN);
        userDefaults.Synchronize();
    }

... and to clear records from the keychain (TODO comment above)

        var securityRecords = new[] { SecKind.GenericPassword,
                                    SecKind.Certificate,
                                    SecKind.Identity,
                                    SecKind.InternetPassword,
                                    SecKind.Key
                                };
        foreach (var recordKind in securityRecords)
        {
            SecRecord query = new SecRecord(recordKind);
            SecKeyChain.Remove(query);
        }
like image 25
InquisitorJax Avatar answered Sep 19 '22 13:09

InquisitorJax


Files will be deleted from your app's document directory when the user uninstalls the app. Knowing this, all you have to do is check whether a file exists as the first thing that happens in application:didFinishLaunchingWithOptions:. Afterwards, unconditionally create the file (even if it's just a dummy file).

If the file did not exist at time of check, you know this is the first run since the latest install. If you need to know later in the app, save the boolean result to your app delegate member.

like image 25
stephen Avatar answered Sep 20 '22 13:09

stephen


@amro's answer translated to Swift 4.0:

if UserDefaults.standard.object(forKey: "FirstInstall") == nil {
    UserDefaults.standard.set(false, forKey: "FirstInstall")
    UserDefaults.standard.synchronize()
}
like image 27
Muhammad Nayab Avatar answered Sep 20 '22 13:09

Muhammad Nayab


This seems to be the default behavior on iOS 10.3 based on behavior people have been witnessing in beta #2. Haven't found any official documentation about this yet so please comment if you have.

like image 28
Stavash Avatar answered Sep 17 '22 13:09

Stavash