Does not work in iOS13.4 simulator
sam-w opened this issue ยท 19 comments
Description
When using the iOS13.4 simulator, SimpleKeychain
reports that it saved successfully. When I try to retrieve the saved object, I get empty data.
Reproduction
- Add this to a fresh Xcode project , e.g. in the AppDelegate.
let keychain = A0SimpleKeychain()
keychain.setString("foo", forKey: "f")
let string = keychain.string(forKey: "f")!
assert(string == "foo")
- Run on iOS 12.4 sim, no assert.
- Run on iOS 13.4 sim, assertion failed.
Environment
- Version of this library used: 0.11.0
- Version of the platform or framework used, if applicable: iOS 13.4 simulator
On iOS 13.3 simulator it works as well. So just the newest iOS simulator seems to be affected.
https://github.com/evgenyneu/keychain-swift does work on iOS 13.4 simulator, so might provide a point of comparison.
Having the same issue here on iOS 13.4 simulator.
Updated my device to 13.4, test suite results:
13.4 Device - All Passing
13.4 Simulator - Failing
Odd situation, working on device implies that code is fine. However, it should work on the simulator of course. So possibly simulator bug or a configuration issue of some kind? Since it was mentioned keychain-swift is okay (I've not checked). cc @Widcket
Did a little debugging and going through previous commits, if you comment this line out then all tests pass in the simulator. So we will dig into this more.
https://github.com/auth0/SimpleKeychain/blob/master/SimpleKeychain/A0SimpleKeychain.m#L305
https://github.com/evgenyneu/keychain-swift does work on iOS 13.4 simulator, so might provide a point of comparison.
Had a look, as suspected it doesn't make any use of LAContext
that I can see.
This seems to be a bug in the iOS 13.4 simulator, as it's reproducible just with the Keychain API:
let laContext = LAContext()
let key = "foo"
let query = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: key,
kSecValueData as String: "bar".data(using: .utf8)!,
// kSecUseAuthenticationContext as String: laContext
] as [String : Any]
SecItemAdd(query as CFDictionary, nil)
let loadQuery = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: key,
kSecReturnData as String: kCFBooleanTrue!,
// kSecUseAuthenticationContext as String: laContext
] as [String : Any]
var dataTypeRef: CFTypeRef?
SecItemCopyMatching(loadQuery as CFDictionary, &dataTypeRef)
print(String(data: (dataTypeRef as? Data) ?? "nope!".data(using: .utf8)!, encoding: .utf8)!)
Uncomment the lines and it will print nope!
instead of bar
.
Possibly related, in the 13.4 simulator hasValueForKey
returns true
for any key:
(lldb) po self
<A0SimpleKeychain: 0x7fd916471b80>
(lldb) po hasValue(forKey: UUID().uuidString)
true
@dionc that method uses SecItemCopyMatching
under the hood. It seems to return a successful status whenever a kSecUseAuthenticationContext
is included:
let laContext = LAContext()
let loadQuery = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: UUID().uuidString,
kSecUseAuthenticationContext as String: laContext
] as [String : Any]
let result = SecItemCopyMatching(loadQuery as CFDictionary, nil)
print("Result: \(result == errSecSuccess)") // Result: true
@sam-w and all, the workaround is out in the 0.11.1 release. Thanks for the report and the input.
Thanks @Widcket. Given that keychain access has proved to be an issue as iOS continues to develop, I'd like to have the option of using an alternative to SimpleKeychain in the future. Please consider reopening auth0/Auth0.swift#367 so we can achieve that.
Thanks for the correction!