iOS keychain randomly returning -25300 error (aka errSecItemNotFound)

Viewed 591

My app is facing a strange keychain behaviour: sometimes it returns -25300 status instead of credentials that definitely exist. The consequence: logged in users randomly become "logged out".

App restart doesn't help, only new user authorization.

Somehow it seems like items just disappear from the keychain.

After looking closer at code that saves and reads data from keychain and comparing it with Apple's samples, I noticed that we don't use kSecAttrService attribute when saving items of kSecClassGenericPassword.

Here some code snippets:

func saveData(_ data: Data, for key: String) -> OSStatus {
        let query: [CFString : Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrAccount: key,
            kSecValueData: data,
            kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]
        return SecItemAdd(query as CFDictionary, nil)
    }
func readData(for key: String) -> String? {
        let query: [CFString: Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrAccount: key,
            kSecReturnData: kCFBooleanTrue as Any,
            kSecMatchLimit: kSecMatchLimitOne
        ]
        var result: AnyObject?
        _ = withUnsafeMutablePointer(to: &result) {
            SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
        }
        return (result as? Data).flatMap {
            String(data: $0, encoding: .utf8)
        }
    }

So, may the absence of kSecAttrService when saving kSecClassGenericPassword items be the reason why keychain items become unreachable for some reason, or is there any other reason?

Thanks

1 Answers

When using the kSecAttrAccessibleWhenUnlockedThisDeviceOnly flag, you have to ensure the protected data is available. There is a method for that in the AppDelegate that notifies you when this event occurs or you could add an observer and listen for the event protectedDataDidBecomeAvailableNotification. Documentation of the delegate method can be found here and documentation of the notification can be found here.

Related