Reading Client Certificate from Keychain

When our app makes an API call to our backend service, we want the app to provide a client certificate in the call.

What API and mechanism we can use so that our app (iOS app store, and Mac with Developer ID) to read a client certificate present in the Keychain.

Please note that the client certificate will be put in the Keychain by an external MDM process. Not sure if an iOS or Mac app can read client certificates from Keychain which they have not put it there in the first place.

Answered by DTS Engineer in 809446022

I’m presuming that you mean digital identity rather than certificate, because access to just the certificate isn’t going to help you much. I talk about that distinction in detail in TLS for App Developers.

To start, I’m gonna focus on iOS. When you install a digital identity on iOS via MDM, the identity is placed into an Apple-only keychain access group. Third-party apps don’t have access to that group. QA1745 Making Certificates and Keys Available To Your App documents that limitation.

There’s one key exception to this rule. A digital identity that’s referenced by an NE configuration profile is placed into a special keychain access group, com.apple.managed.vpn.shared. It’s possible for third-party NE apps to get access to this group. See point #9 in Network Extension Framework Entitlements.

So, if your app contains an NE provider and the digital identity is installed by the same configuration profile as your NE configuration and you’re approved to use com.apple.managed.vpn.shared, you should be able to get that to work on iOS.


The story in macOS is more nuanced. To start, com.apple.managed.vpn.shared is a non-starter on macOS, because:

  • com.apple.managed.vpn.shared is a data protection keychain concept. See TN3137 On Mac keychain APIs and implementations for an explanation of what that means.

  • Your macOS product uses Developer ID, so it must be a system extension.

  • System extensions run in the global context, like a launchd daemon.

  • Code running in that context can’t access the data protection keychain. TN3137 documents that limitation.

However, I’m not entirely sure whether that matters, because last I checked, macOS places digital identities installed by MDM into the file-based keychain. Specifically, if the profile is installed globally, it should go into the System keychain.

The challenge there is access control. The file-based keychain implements access control via an ACL. You’ll only be able to use the identity if you’re listed on the ACL. Honestly, I’m not sure whether the profile import mechanism adds your NE provider to the ACL when the digital identity is associated with an NE configuration.

Unfortunately it’s hard for me to do a realistic test of this. However, it’s something you should be able to test at your end:

  1. Install your app on a managed Mac.

  2. And install its sysex.

  3. Use Apple Configurator to create a configuration profile that configures your NE provider using Certificate [sic] authentication.

  4. Use MDM to push that to your Mac.

  5. Use Keychain Access to see where the digital identity landed, and what its ACL looks like.

Share and Enjoy

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

You tagged your thread with Network Extension. Does that mean your app contains an NE provider? Or is it just a standard app?

Share and Enjoy

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

Yes, it will also have a network extension, but that will be activated once the API that I mentioned above is called and auth is completed.

I’m presuming that you mean digital identity rather than certificate, because access to just the certificate isn’t going to help you much. I talk about that distinction in detail in TLS for App Developers.

To start, I’m gonna focus on iOS. When you install a digital identity on iOS via MDM, the identity is placed into an Apple-only keychain access group. Third-party apps don’t have access to that group. QA1745 Making Certificates and Keys Available To Your App documents that limitation.

There’s one key exception to this rule. A digital identity that’s referenced by an NE configuration profile is placed into a special keychain access group, com.apple.managed.vpn.shared. It’s possible for third-party NE apps to get access to this group. See point #9 in Network Extension Framework Entitlements.

So, if your app contains an NE provider and the digital identity is installed by the same configuration profile as your NE configuration and you’re approved to use com.apple.managed.vpn.shared, you should be able to get that to work on iOS.


The story in macOS is more nuanced. To start, com.apple.managed.vpn.shared is a non-starter on macOS, because:

  • com.apple.managed.vpn.shared is a data protection keychain concept. See TN3137 On Mac keychain APIs and implementations for an explanation of what that means.

  • Your macOS product uses Developer ID, so it must be a system extension.

  • System extensions run in the global context, like a launchd daemon.

  • Code running in that context can’t access the data protection keychain. TN3137 documents that limitation.

However, I’m not entirely sure whether that matters, because last I checked, macOS places digital identities installed by MDM into the file-based keychain. Specifically, if the profile is installed globally, it should go into the System keychain.

The challenge there is access control. The file-based keychain implements access control via an ACL. You’ll only be able to use the identity if you’re listed on the ACL. Honestly, I’m not sure whether the profile import mechanism adds your NE provider to the ACL when the digital identity is associated with an NE configuration.

Unfortunately it’s hard for me to do a realistic test of this. However, it’s something you should be able to test at your end:

  1. Install your app on a managed Mac.

  2. And install its sysex.

  3. Use Apple Configurator to create a configuration profile that configures your NE provider using Certificate [sic] authentication.

  4. Use MDM to push that to your Mac.

  5. Use Keychain Access to see where the digital identity landed, and what its ACL looks like.

Share and Enjoy

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

Thanks for clarifying the difference between digital identity and certificate.

The app has the network extension, but the API that I was talking about had nothing to do with it. It was an oAuth API. Right now, it presents the API call and the presentation of the client certificate that I mentioned had nothing to do with the network extension.

Today, in our Mac app, if we open a URL in the default browser (using UIApplication.open()), and the TLS handshake requires a client certificate, the browser shows a prompt where user can select the client certificate to proceed. User can accept or skip that part.

So if we do that in our iOS app too, will the default browser also prompt the user to select a certificate or we will have to do that programmatically by reading certs from keychain and matching them with what was asked by the TLS handshake ?

So if we do that in our iOS app too, will the default browser also prompt the user to select a certificate … ?

If the default browser is Safari and you call UIApplication.open() with an https URL and the website requires mTLS then Safari will present a digital identity selection UI, just like it does on macOS. Safari builds that list by looking in its keychain access groups, which includes the Apple keychain access group that’s the destination for (non-VPN) identity payloads (com.apple.security.pkcs12).

Well, the actual UI looks quite different but it’s the same concept.

Share and Enjoy

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

Thanks again! You mentioned that 'if the default browser is Safari' and we call UIApplication.open() to open an mtls URL, then Safari will present an identity selection UI. Does this imply that if the default browser on iOS is Chrome or Brave, it will not present the UI ?

Also, Safari builds the identity list by looking at 'its' keychain access group, does this imply that if MDM is supposed to put an identity in the iOS keychain, it has to do something specific so that Safari can read them to show the identity selection list ?

Does this imply that if the default browser on iOS is Chrome or Brave, it will not present the UI ?

The identity selection UI is presented by Safari, not the OS, so it’s really up to the browser developer how it behaves in this case.

Historically browsers behave like normal apps, so they can’t access credentials in the Apple area of the keychain. I don’t know if that’s changed recently.

Share and Enjoy

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

Reading Client Certificate from Keychain
 
 
Q