I'm working on a peace of code that should do the following:
- Store some data in Keychain.
- Get the data only if a user authenticates with Touch ID or Pass Code.
I watched the Keychain and Authentication with Touch ID presentation and understood the following:
If you set the right parameter while adding a new value in to Keychain, next time you'll try to get it out, the system will automatically show the Touch ID popup.
I wrote some code, and my assumption doesn't work. This is what I have written:
//
// Secret value to store
//
let valueData = "The Top Secret Message V1".data(using: .utf8)!;
//
// Create the Access Controll object telling how the new value
// should be stored. Force Touch ID by the system on Read.
//
let sacObject =
SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
.userPresence,
nil);
//
// Create the Key Value array, that holds the query to store
// our data
//
let insert_query: NSDictionary = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccessControl: sacObject!,
kSecValueData: valueData,
kSecUseAuthenticationUI: kSecUseAuthenticationUIAllow,
// This two valuse ideifieis the entry, together they become the
// primary key in the Database
kSecAttrService: "app_name",
kSecAttrAccount: "first_name"
];
//
// Execute the query to add our data to Keychain
//
let resultCode = SecItemAdd(insert_query as CFDictionary, nil);
At first I thought that the emulator had some issue but no, I was able to check if Touch ID is present or not with the following code:
//
// Check if the device the code is running on is capapble of
// finger printing.
//
let dose_it_can = LAContext()
.canEvaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics, error: nil);
if(dose_it_can)
{
print("Yes it can");
}
else
{
print("No it can't");
}
And I was also able to programmatically show the Touch ID popup with the following code:
//
// Show the Touch ID dialog to check if we can get a print from
// the user
//
LAContext().evaluatePolicy(
LAPolicy.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Such important reason ;)",
reply: {
(status: Bool, evaluationError: Error?) -> Void in
if(status)
{
print("OK");
}
else
{
print("Not OK");
}
});
To sum it all up
Touch ID works, but saving a value in to Keychain with the flag to force Touch ID by the system itself is not working - what am I missing?
Apples example
The example that Apple provides called KeychainTouchID: Using Touch ID with Keychain and LocalAuthentication also shows inconsistent result and Touch ID is not enforced by the system.
Tech spec
- Xcode 8.1
- Swift 3