soffes/sskeychain — pull request #76 by liamnichols (2014-09-03 11:45:23+00:00)
Title: Added support for iOS 8/OS X 10.0 AccessControl (Touch ID)

**Please don't automatically merge this!**

I've made some modifications to the `SSKeychainQuery` class by adding some additional properties and methods that essentially allow you to use Touch ID with SSKeychain.

The main change is that i've modified the `save:` method to support the `kSecAttrAccessControl` and `kSecUseNoAuthenticationUI` attributes allowing you to specify a `SSKeychainAccessControl` object via the new `accessControl` property (was wrapping this in an `NSObject` the best approach?).

I have also made changes to `fetch:` and `fetchAll:` allowing you to pass in the `kSecUseOperationPrompt` (displayed when Touch ID is presented) via `useOperationPrompt`.

Finally, I've added a `update:` method as there was no existing wrapper around `SecItemUpdate()`.

With all the above changes, You can now do something like the following to protect items with Touch ID:

SSKeychainQuery *query = [SSKeychainQuery new];
query.service = @"SomeService";
query.account = @"SomeAccount";
query.password = @"SomePassword";
query.accessControl = [SSKeychainAccessControl accessControlWithAccessibility:SSKeychainAccessibilityWhenPasscodeSetThisDeviceOnly flags:SSKeychainCreateFlagUserPresence];

NSError *saveError = nil;
if (![query save:&saveError]) {
NSLog(@"Failed to save item to the keychain: %@", saveError);
} else {
NSLog(@"saved item successfully");
}

Then, you can fetch them like so:

SSKeychainQuery *query = [SSKeychainQuery new];
query.service = @"SomeService";
query.account = @"SomeAccount";
query.useOperationPrompt = @"A prompt displayed when Touch ID alert is shown";

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *fetchError = nil;
if (![query fetch:&fetchError]) {
NSLog(@"Failed to fetch item from the keychain: %@", fetchError);
// `errSecAuthFailed` indicates that the user cancelled the prompt
} else {
NSLog(@"got password: %@", query.password);
}
});

I've not really done much when it comes to maintaining backwards compatibility but I've tested my branch when compiled against the iOS 7 SDK and it still compiles but I would like it if somebody else could check over everything beforehand.

Apple Sample Code: https://developer.apple.com/library/prerelease/ios/samplecode/KeychainTouchID/Introduction/Intro.html

Let me know what you think.

Liam