Does accessing multiple Keychain items with .userPresence force multiple biometric prompts despite reuse duration?

Hi everyone,

I'm working on an app that stores multiple secrets in the Keychain, each protected with .userPresence.

My goal is to authenticate the user once via FaceID/TouchID and then read multiple Keychain items without triggering subsequent prompts.

I am reusing the same LAContext instance for these operations, and I have set:

context.touchIDAuthenticationAllowableReuseDuration = LATouchIDAuthenticationMaximumAllowableReuseDuration

However, I'm observing that every single SecItemCopyMatching call triggers a new FaceID/TouchID prompt, even if they happen within seconds of each other using the exact same context.

Here is a simplified flow of what I'm doing:

  1. Create a LAContext.
  2. Set touchIDAuthenticationAllowableReuseDuration to max.
  3. Perform a query (SecItemCopyMatching) for Item A, passing [kSecUseAuthenticationContext: context].

Result: System prompts for FaceID. Success.

  1. Immediately perform a query (SecItemCopyMatching) for Item B, passing the same [kSecUseAuthenticationContext: context].

Result: System prompts for FaceID again.

My question is:
Does the .userPresence access control flag inherently force a new user interaction for every Keychain access, regardless of the LAContext reuse duration? Is allowableReuseDuration only applicable for LAContext.evaluatePolicy calls and not for SecItem queries?

If so, is there a recommended pattern for "unlocking" a group of Keychain items with a single biometric prompt?

Environment: iOS 17+, Swift.

Thanks!

I'm working on an app that stores multiple secrets in the Keychain

What keychain item class are these? kSecClassGenericPassword? kSecClassKey? Or perhaps a mix?

I’m asking because of the context discussed here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for your reply (You are a legend at Apple!)

The linked conversation is using an interesting approach, where a SecureEnclave protected key pair protected with .userPresence could be used to manually encrypt tokens before storing them in the keychain.

Just found that using kSecMatchLimit with kSecMatchLimitAll effectively limits FaceID prompts to a single one.

kSecMatchLimitOne in separate calls will produce one faceID prompt per call.

Does accessing multiple Keychain items with .userPresence force multiple biometric prompts despite reuse duration?
 
 
Q