NSPinnedDomains in AppClip Info.plist doesn't seem to take for URLSession API

I submitted a feedback asking what would be safe prevent MITM attacks against CloudKit web APIs, pinning against the CA was an okay'd implementation.

This is the response I got in my feedback: FB9445034

You can pin to the various Apple CA or sub-CA certificates that can be found here:

https://www.apple.com/certificateauthority/public/ https://www.apple.com/certificateauthority/

All the certificates for CloudKit and iCloud web APIs have cert chains that point to the certificates listed.

I have followed this article Identity Pinning and modified my App Clip info.plist accordingly to pin against CloudKit Web Services (https://api.apple-cloudkit.com). I intentionally mucked up the identity pin to verify my URLSession requests failed. I didn't receive any URLSession errors in my App Clip or Application targets when I had the plist updates in both.

In reading these other forum posts I'm curious if the Identity Pinning is supported in App Clips or not.

https://developer.apple.com/forums/thread/678081 https://developer.apple.com/forums/thread/681734

Replies

First, I have no idea if using NSPinnedDomains in an App Clip is supported or not. My recommendation to you here would be to get this working in an app first, and then port it to a App Clip to check on the status of the functionality there.

Regarding the status of pinning a public key hash to a CA, I have made some progress since those previous posts; Essentially, what you need to do is identity the CA Public Key that you would like to pin your app's network request to and then download that certificate from the CA, in this case Apple PKI. So, for example a Public Key usually looks like:

# Note that this is just and example Public Key, not the actual one you are looking for:

08 3B E0 56 90 45 46 C1 A1 82 6A C9 59 92 C7 4B 

or

08:3b:e0:56:90:45:46:C1:a1:82:6a:c9:59:92:c7:4b 

Find the CA certificate with the Public Key that matches the Public Key of the domain you would like to pin a request to and download the CA certificate as a PEM. From there, you can use the public key hash command to hash and encode the public key of the certificate:

$ cat YouCA.crt.pem | openssl x509 -inform pem -noout -outform pem -pubkey | openssl pkey -pubin -inform pem -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Which outputs something like the following (note, also not a real value):

r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=

Now, use this with the following Info.plist dictionary:

<key>NSPinnedDomains</key>
<dict>
	<key>the-domain.com</key>
	<dict>
		<key>NSIncludesSubdomains</key>
		<true/>
		<key>NSPinnedCAIdentities</key>
		<array>
			<dict>
				<key>SPKI-SHA256-BASE64</key>
				<string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string>
			</dict>
		</array>
	</dict>
</dict>

Now, run this and make sure that it works. Now, change the last few characters on the hash and it should NOT work: A5E= -> A6E=.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
  • Thanks Matt, if I get things working in my main app target I'll be sure to rinse and repeat for the app clip. Since my Feedback and the reply I've learned more about CloudKit Web Services (for interacting via that App Clip). I assume I should expect the "DownloadURL" for the CKAsset representations to also be behind the same PKI / certs right?

  • You should double check the CA being used to be sure. While Apple does issue certificates from the same set of intermediates and roots for a lot of our services, this doesn't mean that all services use the same root and intermediate.

Add a Comment