iphoneiosbackgroundkeychainlockscreen

iOS KeyChain not retrieving values from background


I am currently storing the username (email) and a salted hash of the email and password in the iOS KeyChain. I'm using the ARC'ified version found here.

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
[wrapper setObject:APP_NAME forKey:(__bridge id)kSecAttrService];
[wrapper setObject:email forKey:(__bridge id)kSecAttrAccount];
[wrapper setObject:token forKey:(__bridge id)kSecValueData];

This all works fine when I need to pull the token out for my network calls while the app is active. It works for logging in from a clean startup, as well as all the network calls throughout. The trouble starts when the app is in the background.

Keep in mind, this only happens sporadically and I have yet to pin it down to a specific iOS version or device.

The user trips a location (region monitoring) and I want to update the server with their status. I try to pull the token out of the keychain, the same way I do for every other network call, and update the status. But for some users, the value is nil. Without it, I can't update the network stuff. Why would this work for most, but not for a small percentage?

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];

I've gone back to the non-ARC version of the keychainwrapper, but I still get the same results. I would appreciate any feedback on this. It is only a small part of my users, but it is an issue I would like to fix and not worry about.

Also, all of my background work is set up in a backgroundTask to prevent things from timing out. I'm not having any issues with the work surrounding the keychain, but I don't let things go forward until my token is filled.

EDIT I've figured out my issue with they keychain not retrieving values from the background. I will post the answer below and accept it as I feel this question may become valuable to others later.


Solution

  • My question was close to the mark for the reason why, but not quite. After reading through blog after blog, tutorial after tutorial, I finally found one that gave off a hint of what might be happening.

    Locked home screens. The keychain tutorials always left the accessibility settings for the keychain blank, so it would default to Apple's lowest/safest access level. This level however doesn't allow keychain access if the user has a passcode on the lock screen. Bingo! This explains the sporadic behavior and why this only happens to a small percentage of users.

    One line of code, solves the entire mess.

    [wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];
    

    Add this line where I'm setting the username and password values. Works like a charm. Hope this will help someone out there. It confounded me for quite a while until I was able to put the pieces together.