TouchID & thisDeviceOnly on macOS

With TouchID and a secure enclave coming to some machines running macOS (as announced at today's event) it would be nice to know how third party apps may use Touch ID and whether items stored in the macOS keychain will have the ability to be as tightly bound to the device (via keys entangled with secrets that never leave the secure enclave) as they are on iOS.


Can someone point me to what I should be reading or looking at for those?

Replies

… it would be nice to know how third party apps may use Touch ID …

If you look at the macOS SDK included with Xcode 8.1 (specifically,

<Security/SecItem.h>
,
<Security/SecAccessControl.h>
and
<LocalAuthentication/LAContext.h>
) you’ll find that many of the declarations that were previously only available on iOS are now available on macOS. This should allow you to:
  • generate keys on the Secure Enclave using

    kSecAttrTokenIDSecureEnclave
  • use LAContext to manually authenticate

  • protect secrets in the keychain with

    kSecAccessControlTouchIDAny

Let us know if you hit any snags.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hey Quinn,


I'm working on the same problem, and since I don't have one of the new Macbooks yet. I'm testing with saving a keychain item with kSecAccessControlDevicePasscode instead of kSecAccessControlTouchIDAny. Theoretically if I get everything working with kSecAccessControlDevicePasscode then I should be able to just switch that to kSecAccessControlTouchIDAny to use Touch ID.


Now I've encontered something weird... When using using SecItemCopyMatching to check if the keychain item exists, I'm also asked for my password. Even though I'm not requesting any secret data to be returned.


NSDictionary* query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                         (__bridge id)kSecAttrService: @"Service",
                         (__bridge id)kSecAttrAccount: @"Account",
};
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query), NULL);


Once the item is stored, the above code will also ask for the user's password making testing for its existence difficult (to adapt your UI for example). I have very similar code on iOS and it works has expected.


Is this on purpose?

Is there a recommended way to test TouchID on a Mac that doesn't have it? Sort of like how you can emulate the new Touch Bar?


I'd like to add it to my Mac app.

Are you setting

kSecAttrSynchronizable
? Without that the SecItem item API shims you over to the file-based keychain implementation, which is probably not what you want in this sitation.

ps If you’re not familiar with the iOS-style vs traditional Mac keychain dichotomy, check out this post, which explains some background to this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Is there a recommended way to test TouchID on a Mac that doesn't have it?

Not that I’m aware of. Even if there were, given the sensitive nature of anything to do with Touch ID, I’d be reluctant to ship code for this that hasn’t been tested on real hardware.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I am familiar with the iOS style API. That's what I'm using in both iOS and Mac code.


I'm not explicitely setting the kSecAttrSynchronizable because I'm also setting kSecAttrAccessibleWhenUnlockedThisDeviceOnly. I've created radar://29064415

Agreed. That's why I'm holding off until my new MBP arrives. I'm quite surprised that 1Password has already shipped their update with TouchID support for Mac.