NSHTTPCookieStorage loosing cookies if app starts before phone has been unlocked at least once after a reboot

StackOverflow https://stackoverflow.com/questions/22646726

Question

Problem

As the title says, I'm currently experiencing an issue where the NSHTTPCookieStorage is loosing the cookies for our app when it's initialised in background before the phone has been unlocked at least once after a reboot.

Once the cookies are lost, they can't be recovered in any way, forcing the user to re login to retrieve a new set of cookies and recover a session.

If app activity is registered for the first time AFTER the user has unlocked her/his phone, then everything works like a charm.

Context:

  • This issue happened to us using NSURLRequest and NSURLSession as well as using ASIHTTP and AFNetworking with automatic cookie handling, so we came to the conclusion its affecting the whole NSHTTPCookieStorage class.

  • Our app has SLC (Significant Location Change monitoring) so its
    triggered in background automatically.

Steps to reproduce

  1. Make a demo app that performs a network call ("Lets call it CALL A"), to authenticate to a server, getting some cookies in response to that.
  2. Perform a second call (Lets call it "CALL B") that requires this cookies to be sent in order to work. If everything goes well, cookies should be automatically managed and sent to the server accordingly.
  3. Make your demo app be able to execute some background stuff, for example enable SLC monitoring. In the execution of this background behaviour perform "CALL B" again (If it's inside a background task or not doesn't really matter for the test purpose)
  4. Reboot your phone and DON'T unlock it.
  5. Wait until the SLC, or the background behaviour you chose is triggered and CALL B is done.

    TIP: You can disable and enable Airplane mode to force an SLC trigger on the device.

    Problem: If in that time a significant location change is triggered, the app looses all the cookies forever, without any chance of recovering them in any way.

Any help or idea will be appreciated.

Was it helpful?

Solution

Seems that iOS is having this same issue but with cookies stored on NSHTTPCookieStorage.

I've already created a radar so feel free to add more so this issue is pushed up a bit in the queue. Radar number is 16237165.

In the meanwhile, you can perform the following workarounds:

  1. Handle cookies manually (aka not rely on iOS automatically managing cookies and storing them in the NSHTTPCookieStorage class). But DON'T use NSUSerDefaults because its having the same issue.

  2. Prevent all network activity before phone has been unlocked at least once. This is the option we took and we did the following:

    • Create a file in disk with the NSFileProtectionCompleteUntilFirstUserAuthentication permission.
    • Before making any network call, check if the app is able to read that file. If it is, it means phone was unlocked at least once, so you are good to do the call without loosing cookies.

Here is a code sample:

static BOOL phoneIsUnlocked = NO;

//If this var is true, then avoid re checking if file has permissions (Cause if it was granted permissions once, it will have access now)
if(phoneIsUnlocked) return phoneIsUnlocked;

//If phone has never been unlocked, prevent all networking stuff just to make sure cookies are not lost due to an ios7 bug.
//Creates a file with NSFileProtectionCompleteUntilFirstUserAuthentication permissions. If the app is able to read it, it means the phone was unlocked at least once after a reboot.

//Get the file path
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:@"a.secure"];

//create file if it doesn't exist
if(![[NSFileManager defaultManager] fileExistsAtPath:fileName])
    [[NSFileManager defaultManager] createFileAtPath:fileName
                                            contents:[@"secure" dataUsingEncoding:NSUTF8StringEncoding]
                                          attributes:[NSDictionary dictionaryWithObject:NSFileProtectionCompleteUntilFirstUserAuthentication
                                                                                 forKey:NSFileProtectionKey]];

NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:fileName];
phoneIsUnlocked = file != nil;     //If file is not nil, the phone has been unlocked
[file closeFile];

OTHER TIPS

From your described behaviour it seems that the protection on the underlying file store used by NSHTTPCookieStorage has been set "Complete until first login".

As you can't change where and how NSHTTPCookieStorage stores your data you have a couple of choices:

  1. Use a different method for storing your cookies
  2. Check the protectedDataAvailable property of UIApplication and defer your updates until the device is unlocked. You can register for the UIApplicationProtectedDataDidBecomeAvailable notification to be advised when the device is unlocked.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top