We have a Mac Catalyst app which uses the keychain to store secrets. We’ve received a report from a user that the app ran fine for a number of days, but has recently started failing to store OR retrieve that secret and displays an in-app alert to that effect. Top line is that both SecItemAdd and SecItemCopyMatching return errSecInteractionNotAllowed, though they have been working just fine previously.
I know that on iOS this issue can be the result of the device being locked while the app operates in the background. But the user is actively using the app when this happens (ergo the device should be unlocked). Is there something more about keychains on macOS that I’m missing? Is this something particular to Catalyst? We haven’t been able to reproduce it. Any help would be appreciated! From an actual solution to suggestions for reproducing the bug to suggestions on differences between macOS and iOS in this respect.
The secret in question is stored with the following dictionary:
let insertQuery: [String:Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecValueData as String: Data(secret.utf8), // `secret` being a String with the secret’s value
kSecAttrService as String: serviceTag, // `serviceTag` being a String with the name of the secret
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
let insertQueryCFValue = query as CFDictionary
let status = SecItemAdd(insertQueryCFValue, nil)
Looking up the secret goes like this:
let findQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceTag, // As above
kSecMatchLimit as String: kSecMatchLimitOne,
kSecReturnAttributes as String: true,
kSecReturnData as String: true
]
let findQueryCFValue = findQuery as CFDictionary
var item: CFTypeRef?
let status = SecItemCopyMatching(findQueryCFValue, &item)
In both code snippets status == errSecInteractionNotAllowed
.