Making Sense Of iOS Provisioning
If you’re new to iOS development, whether you are using Xamarin, native, or another platform, you will want to debug and develop on an actual iOS device. In addition, you probably want to deploy alpha or beta versions of your app to testers running on various iOS devices in real world scenarios. If you’re developing for Android, this process is really easy as the Android operating system allows users to easily side load applications. However, the opposite is true for iOS devices. In fact, setting up an iPhone or iPad for development can be very frustrating and confusing, especially if you’re new to iOS development.
Xamarin and Apple both have excellent documentation on how to properly provision an iOS device for debugging, and testing. Though it is really easy to follow the step-by-step procedures on creating the proper provisioning profiles, what I find lacking in such documentation is how provisioning works. In this article, I’m not going to explain how to create provision profiles. There’s plenty of documentation out there. I’m going to explain how provisioning profiles work, and why the iOS operating system needs them. A solid understanding is necessary if you run into any issues or errors such as “No valid iOS code signing keys found in keychain”, or “Code Sign error: Provisioning Profile ‘xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx’ can’t be found”.
Apple Rules iOS With An Iron Fist
Unless you jail break an iOS device, side loading applications outside of the Apple App store is strictly prohibited. This also applies to any potential developers who want to develop iOS applications. iOS is Apple’s realm, and they rule it with an iron fist.
Whether you agree with their philosophy or not, Apple, and only Apple, can allow an application to run on an iOS device. Any piece of software that does not have Apple’s blessing will not execute. Yes, it’s harsh, and provides some major inconveniences for developers, but Apple calls the shots here.
So how can developers and testers install, execute, and debug their applications on actual devices? <sarcasm>The answer Apple has so graciously blessed us with </sarcasm> is with Provisioning Profiles. But before I explain what Provisioning Profiles are, it’s necessary to understand how iOS determines whether or not an application is allowed to execute.
How Apple Allows iOS Apps To Run
As I mentioned earlier, only Apple allows an application to execute on iOS. When developers submit their apps to the App Store, Apple manually installs your application onto test devices and makes sure the application performs as described (in your App Description), does not crash under normal usage, and passes their App Store Review Guidelines. Once the app passes the review process, it is certified for release.
Apple then takes your application, and re-signs it with their security certificate. This is the magic key here. Any application that is signed by Apple is “blessed” to run on any iOS device indefinitely. From here, the app is ready to be published on the App Store and available to your users.
So if only apps that are signed by Apple are allowed to run on iOS devices, how are developers and testers allowed to install their applications for debugging and testing? Apple will allow developers to run their apps on iOS devices through the use of Provisioning Profiles.
Through the use of a Provisioning Profile, Apple will allow developers to run their apps on an iOS device on Apple’s behalf. However, this isn’t the same “side loading” you can do on Android. Provisioning Profiles do impose limitations on your app. I’ll explain those in a moment though.
Certificates? Provisioning Profiles? UDID? Say What!?!?!?
As we know from the Xamarin documentation, there are several steps we need to do in order to create a provisioning profile. They include:
- Registering for the Apple iOS Developer Program ($99 USD / year).
- Requesting a security certificate from Apple.
- Creating an App ID for your app.
- Adding UDID of your test and development iOS devices
- Creating Your Provisioning Profile (selecting your UDID, Entitlements, App ID, Certificate, etc)
The process of creating a provisioning profile is somewhat long and confusing if you’ve never done this before. But both Xamarin and Apple provide great step-by-step document on how to create one. The issue that I and many developers face is that though we follow the step by step process, and are successful, we really did not understand what we did and why we did it.
The Provisioning Profile is a special hall pass issued to you by Apple that allows you to execute your application on iOS devices for development and testing purposes. This gives you just enough flexibility for debugging and testing on device, including distributing your app to beta testers. However, it does not give you the flexibility to distribute your app in production to your users (unless you use an Enterprise profile, but I’ll get to that later). Development and AdHoc Profiles do impose limitations that I’ll explain in another section. Remember, Apple rules the iOS realm very aggressively. But they do give you just enough flexibility to do your job.
It is important to know that a provisioning profile consist of several items, but the most common ones you need to know are:
- Your App ID
- Your signing certificate issued by Apple
- A list of UDID for devices that the app is allowed to run on.
- Any special Entitlements the app is allowed to use such as Push Notifications, Passbook, HealthKit, CloudKit, etc.
What is an App ID
An app ID is a unique identifier for your application. This is how iOS identifies your application. In addition, Provisioning Profiles need to know your App Bundle ID in order to allow it to run. So it is important to keep your App ID in your apple developer portal, and your App Bundle ID in your iOS project settings the same. The App Bundle ID must be in reverse DNS format, such as com.CompanyName.AppName. For example, an App Bundle ID can look like these:
In addition, the App ID should only contain alpha-numeric characters, hyphens (-) or periods(.). Special characters (such as $, !, @, etc) are not allowed. A common pitfall developers face because the tools do not prohibit you from using special characters. And the error messages this creates are not very obvious. But if you do get errors regarding your App ID or App Bundle ID, the first thing to check is if they are the same, and second make sure they don’t contain special characters.
What Are Certificates?
Once you are registered as an Apple iOS Developer, you need to log into the Developer Portal and request a distribution certificate from Apple. What is a distribution certificate? This is a security certificate that is unique to you, and is issued by Apple. This is what apple uses to uniquely identify you as a developer or publisher of an app. Think of this as your unique serial number that Apple uses to identify you. The private key for the distribution certificate is used to sign your application. Because the certificate was issued by Apple, Apple uses this to verify your identity as a publisher, and not someone else publishing your app pretending to be you.
The certificate contains a public/private key pair. Like a standard security certificate, you MUST keep your private key private, and backed up in a safe place. It should not be shared, especially for a production certificate. As said earlier, signing your application with your private key verifies to Apple that the app was developed by you or your company.
To backup your key, or to export it to a different Mac (such as a production build server), you need to use the Apple KeyChain tool to export your key. If you ever lose your key, then you must log into the Apple Developer portal, revoke your certificate, and request a new one. In turn, you must revoke all other provisioning profiles and re-create them with your new certificate. This can be a big hassle, so I recommend backing it up in a safe place. In order to back up your private key, you need to export it from the Apple Keychain too. For instructions on how to do this, check out this site.
There are also two types of signing certificates. There are Development certificates and Production certificates.
Development certificates should be use for individual developers who are actively debugging and developing an application. This gives developers the flexibility to constantly re-deploy apps to their test devices and debug code through their IDE such as Xamarin Studio, Visual Studio, or XCode. They are not meant to identify you as an app publisher in the App Store. Apple enforces this by not allowing Production Provisioning Profiles to be signed by Development certificates.
Production certificates should be used in either a Production setting (your final build for the App Store), or a QA build that is distributed through Apple’s TestFlight Beta or another app test distribution system. These certificates identify you as an App Store Publisher to Apple or as a Test Distributor and can only be used with Production Provisioning Profiles.
What Are UDIDs?
UDID stands for Unique Device Identifier. This is a string that uniquely identifies an iOS Devices. All iOS devices have UDIDs programmed in their firmware. They cannot be changed, and no device shares the same UDID. A provisioning profile needs a list of UDIDs so that it knows which devices the app is allowed to run on. If the UDID of the device is not listed in the provisioning profile UDID list, then iOS will not allow the app to install or execute.
What Are Entitlements?
You can think of Entitlements as special permissions, or capabilities an app needs to interact with other Apple services that are external to your applications. For example, Push Notifications is an external Apple service that is independent of your application. Because iOS applications are sand-boxed, it can’t directly interact with other Operating System services, such as Push Notifications without an Entitlement. In order for your app to receive Push Notifications, your provisioning profile must have the correct Entitlement enabled. Types of Entitlements include, but are not limited to:
- Push Notifications
- Cloud Kit
- Health Kit
- Game Center
- In-App Purchases
- Keychain Sharing
These are all different Apple services that are available for your app to use. But your app needs permission to use them. By default, provisioning profiles do not include any entitlements. If you want your app to have any of those special capabilities, you must enable the correct entitlement in your provisioning profile. In addition, you also have to specify the proper entitlements in your iOS App settings, and they must match the list of Entitlements on your provisioning profile. This what allows your application to use and communicate with external Apple services.
Bringing it All Together With Provisioning Profiles
As I mentioned earlier, Provisioning Profiles are created in your Apple Developer Portal. They consist of your App ID, your distribution certificate, a list of UDIDs, and a list of any special Entitlements the app needs. There are other things that are included in a provisioning profile, but these are the most common items developers need to know.
Now we have a high level of understanding what a provisioning profile consists of. Now we need to understand how our application maps to a provisioning profile. From the Xamarin Documentation, we know we need to specify a certificate (Identity) and a Provisioning profile to use in our project settings. This is done after you create them in the Apple Developer Portal, and then download/install them onto your Mac. The easiest way is through XCode, or they can be downloaded and installed onto your Keychain manually.
From the image above, we can see certain items need to be matched up before your app can be installed onto an iOS device for debugging and testing. First your Bundle ID must match the App ID of the provisioning profile. Second your list of Entitlements in your project settings must match the list of Entitlements specified in the provisioning profile. If no Entitlements are needed, then this is ignored. Third, the UDID of your device must be in the list of device UDIDs in the provisioning profile. If the device UDID is not in this list, the app will not be allowed to install or run.
And lastly, after the app is compiled, it is signed with the private key of your distribution certificate (“Identity”). This is an important step because the private key of the certificate MUST match the public key of the Certificate in the provisioning profile. This tells Apple that you indeed compiled this app, and it was not someone pretending to be you. If the private/public key pair is invalid, then the app will not allowed to be installed or executed. Once all these checks have passed, iOS will allow the application to be installed and executed.
Types Of Provisioning Profiles
There are 4 different types of provisioning profiles. They are Development, App Store, Ad-Hoc, and Enterprise. They are used for different purposes, and should be only used for those purposes.
Development Provisioning profiles are used only while developing an application. Developers use these profiles so that they can actively debug their code, and test on different devices. They are not designed to be used for mass distribution. Only use these profiles for development and debug builds. These are assigned to individual developers, and are used to identify them. Also, Development Provisioning Profiles can only be created with Development Signing Certificates (this is important to remember).
Ad-Hoc Provisioning profiles are similar to development profiles, but can be used for distribution to QA Testers. Ad-Hoc provisioning profiles can only be created with Production (Ad-Hoc) Certificates (this is important too). Though Ad-Hoc profiles are similar to development profiles, there is one key difference to note between the two that make their intended usage differ. The key difference is when you want to test out different Entitlement services, such as Push Notifications.
For example, if your app supports push notifications, you would want to test your QA build using your Production Push Notification Certificate and the live APNS servers (and not the development ones). In order to do this, you’ll have to deploy your app using an Ad-Hoc profile, which includes your Production certificate. And when you’re performing QA for your app, you want to resemble close to production as possible. This is just one example of why you want to use Ad-Hoc for QA testing and distribution. There are many similar scenarios like this, so get in the habit of using Ad-Hoc profiles and certificates for QA distribution and never use Development profiles for this purpose.
App Store Provisioning Profiles are to be used after your app has passed QA and is fully tested to the best of your ability. This is the profile you want to use when you submit your application to the Apple App Store. In fact, Apple will not let you submit your app if it is not built with an App Store Provisioning Profile. There are some key differences here. One major different is that a list of UDIDs is not required for an App Store Provisioning Profile. This is okay because when Apple approves your app to be distributed to the App Store, they re-sign your application using their own signing certificate and profile. This is the magic key that allows your app to run on all iOS devices without limitation. Though the App Store Provisioning is necessary because this is Apple’s verification that the submission has come from you or your company and not someone else pretending to be you.
Enterprise Provisioning Profiles are very similar to Ad-Hoc Provisioning profiles, but with some key differences. The first difference is that in order to obtain an Enterprise Provisioning Profile, your company must join the Apple iOS Developer Enterprise Program ($299 USD / year). This is a separate program than the “iOS Developer Program” that you may already be registered to. Joining the Enterprise Developer Program is strict, and a key requirement is that your company must have a valid D-U-N-S number registered with Dun & Bradstreet. And they are only issued to legal business entities. If your business does not have a valid D-U-N-S number, then Apple will not allow you to join the Enterprise Developer Program.
The Enterprise Developer Program allows companies to create and distribute in-house applications to their employee’s iOS devices through the use of the Enterprise Provisioning Profile. As stated earlier this is similar to Ad-Hoc profiles, but with one key difference. The key difference is that Enterprise Provisioning Profiles do not need a list of UDIDs. This give companies the flexibility to install their in-house proprietary apps to an unlimited number of devices that are registered with their enterprise. Ad-Hoc profiles on the other hand must have a list of UDIDs that the app is allowed to run on. And if it’s not in the list, the app will not install or run.
Limitations Of Provisioning Profiles
As you’ve learned about the different types of profiles and their intended purposed, you’ve probably guessed on what their limitations are. These limitations are enforced so that they are used for their intended purposes. But here’s a quick summary:
Development profiles expire when the development signing certificate expires. The development signing certificate has an expiration date of one year after it is created. After the profile expires, the app will no longer be able to execute. In fact if you try to start an app with an expired provisioning profile, you’ll get an error message stating so. When this happens, you simply have to request another development signing certificate from Apple, and use that to create another developer provisioning profile. After that, you have to update your iOS App settings to use the new certificate and profile. This is not disruptive to your users because these profiles only applies to an individual developers test devices and not meant for mass distribution. Another limitation is that the profile will only allow the app to install and execute if the device UDID is in the Profile list of UDIDs. If it’s not in the list, it will not install or run.
Ad-Hoc profiles have the same limitations as development profiles and the signing certificate expires after one year. When the signing certificate expires, so does the Ad-Hoc provisioning profile. When this happens, you must request another certificate and re-create another ad-hoc profile like stated above. And just like a Development Profile, a list of UDIDs is also necessary. The prevents the app from being executed on “unauthorized” devices.
AppStore profiles have less limitations, as a list of UDIDs are not necessary. Though they do also expire after one year. But this is not an issue because this type of profile is used only to submit your app to the Apple App Store. As stated above, this is only used to verify your identity to Apple. Once the profile expires, you just create a new production certificate, and a new App Store Provisioning Profile. Then resubmit your next app or app update with this profile. Since the certificate and profile was issued by Apple, they can verify your identity. This will not affect your users because Apple re-signs your app with their own magic certificate and profile, which allows it to run on all iOS devices indefinitely.
I know this post was a little long, but I hope is was helpful in understanding how device provisioning works with iOS. The purpose of the article was not show give you a step-by-step procedure in creating provisioning profiles. There is plenty of documentation that shows you how to do that. But what I found lacking was a description of how they work, and why they work the way they do. I’ll confess that the first time I successfully create provisioning profiles, I did not understand what was going on. I was just following the step-by-step procedure. After I succeeded, I forgot about everything I had read about. It wasn’t until I migrated to a new development computer, and shortly after (by coincidence) when one of my security certificates expired I spent literally days trying to figure out what the heck was going on.
After a good nights rest, I decided to go back to the basics. I spent the time researching the how and why provisioning profiles work. Once I felt I had solid understanding, the many error messages I was getting started to make sense. As it turns out, the error messages (no private key found, device not listed in provisioning profile, etc) told me exactly what was wrong. It’s just I didn’t understand them until I understood how provisioning profiles worked. I spend several days trying to figure out what was wrong, but once I understood the error message (and how profiles work), I was able to fix my issues in about 10 minutes!
This article is the summary of all my notes and research I’ve done on this. I constantly refer back to them when I have issues, and even share them with other colleagues. And I hope that you, as iOS developers find this useful as well. So here’s a quick run down on what we’ve learned so far:
- Whether you philosophically agree or not, Apple and only Apple will allow an app to execute.
- Apple does allow developers to debug and distribute their app for testing on Apple’s behalf through the use of Provisioning Profiles.
- A Provisioning Profile is a special hall pass issued to you by Apple that allows you to execute your application on iOS devices for development and testing purposes. This comes with limitations such as certificate expiration and a list of device UDIDs that app is allows to run on.
- Provisioning profiles consists of many things, but the most common developers need to worry about are the App ID, Distribution Certificate, the list of Entitlements, and the list of UDIDs.
- Apps signed with a provisioning profile, must have a one to one mapping from the app project settings and the provisioning profile.
- Only use the different types of provisioning profiles for their intended purpose (Development, Ad-Hoc, App Store, Enterprise).
- Once you have a solid understanding how device provisioning works, troubleshooting error messages is easy as they explicitly state exactly what the problem is. Once you understand what the problem is, it’s easy to correct.
Thanks for bearing with me and reading along. This is probably one of my longer articles, but I felt is was very important to iterate the important details. If you have any questions or comments (or corrections, lol) feel free to leave a comment below!