KeychainAccess
KeychainAccess copied to clipboard
Touch/Face ID prompt does not show on the Simulator.
Hello, the prompt for Touch/Face ID only works on a real device. On the simulator, the secure value is just directly read or written to without a prompt.
Googling, I found another user of this framework with the same issue here. So, my question is, how do I get the Touch/Face ID prompt to show on the simulator?
This may be unrelated response however, in the documentation for AuthenticationPolicy when interacting with TouchID / FaceID following the example here:
let keychain = Keychain(service: "com.example.github-token")
DispatchQueue.global().async {
do {
// Should be the secret invalidated when passcode is removed? If not then use `.WhenUnlocked`
try keychain
.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence)
.set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
} catch let error {
// Error handling if needed...
}
}
If you follow the .userPresence
AuthenticationPolicy it says above this variable...
/**
User presence policy using Touch ID or Passcode. Touch ID does not
have to be available or enrolled. Item is still accessible by Touch ID
even if fingers are added or removed.
*/
Yes it uses Touch ID or Passcode but then goes on to say does not have to be available or enrolled
.
Based on this, I have to ask the following:
- Which policy are you using to add or remove an item?
- perhaps the policy you are setting doesn't have the constraint of
must have
enrolled finger/face.
If you look at this policy however,
/**
Constraint: Touch ID (any finger) or Face ID. Touch ID or Face ID must be available. With Touch ID
at least one finger must be enrolled. With Face ID user has to be enrolled. Item is still accessible by Touch ID even
if fingers are added or removed. Item is still accessible by Face ID if user is re-enrolled.
*/
@available(iOS 11.3, OSX 10.13.4, watchOS 4.3, tvOS 11.3, *)
public static let biometryAny = AuthenticationPolicy(rawValue: 1 << 1)
It requires
at least 1 enrolled item and enforces this policy
After making a toy app that integrates with KeychainAccess,
I've been able to reproduce the issue where the simulator does not show any Touch / Face ID prompts even though the policy is set explicitly to biometryAny
The following is my setup
- Simulator running iOS 13.6
- KeychainAccess running v. 4.2.0 installed via Swift Package Manager
- MacOS running 10.15.6
- XCode version : 11.6 (11E708)
The project is a SwiftUI 1.0 project with iOS target 13.6
Here's a snippet of code that sets and gets the item
import KeychainAccess
class BiometricsViewModel: ObservableObject {
private let keychain = Keychain(service: "com.example.backgrounddownload")
@Published var hasSetSecureItem: Bool = false
@Published var retrievedSecureItem: String? = nil
func setSecureItem(with value: String) {
DispatchQueue.global().async {
do {
try self.keychain
.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .biometryCurrentSet)
.authenticationPrompt("Authenticate to set secure item.")
.set(value, key: "test_key_2")
} catch let error {
print(error)
}
}
}
func retrieveSecureItem() {
DispatchQueue.global().async {
do {
let value = try self.keychain
.authenticationPrompt("Authenticate to access secure item")
.get("test_key_2")
DispatchQueue.main.async { [weak self] in
self?.retrievedSecureItem = value
}
} catch let error {
print(error)
}
}
}
}