This time I'm going to explain everything about the mysterious iOS provisioning process and the structure of a provisioning profile.
What is provisioning?
iOS is a very secure operating system. You can only install apps on your device that have been approved by Apple so your application needs to be digitally signed before it gets published to the App Store. The signed binary helps Apple ensure the content is coming from the actual developer (team), so it's not compromised or altered by a third-party hacker. Unsigned apps cannot be published on the App Store, so this process allows Apple to be the gatekeeper for their operating system. Basically, they can simply disable developer accounts or revoke certificates if they don't follow the rules. If that happens, you won't be able to install apps from that developer anymore.
However, if you develop an application you might want to test it on a real device before the submission process. That’s what provisioning process is for: you can sign your application with a special file called provisioning profile. This file is a collection of digital entities that connects physical devices to authorized developer teams. You can generate a provisioning profile for your application by using the Apple developer portal. 👍
Now that you know what provisioning is and why it is so important, let's take a deeper look at on provisioning profiles and certificates.
What kind of provisioning profiles are there?
There are 4 types of provisioning profiles:
The development profile gives you the ability to test your apps on your physical devices. It contains the unique device identifier for every single test device. You can only run your app on the devices that are included in the development profile.
The distribution profile has no such limitation because it's used to distribute your app through the App Store. If you want to submit your app for approval, you have to sign it with a distribution profile. If Apple approves it, your app can be published to the store, and this means it can be installed by anyone. 😊
You can also create an ad-hoc profile which is basically a distribution profile with device identifiers. Apps signed with the ad-hoc distribution provisioning profile can be installed on a limited number of designated devices through websites, mails or OTA. It's good for public beta testers, QA teams or client demos.
The in-house profile is only available for enterprise developers, it can be used for internal distribution for non-registered devices too. This means that you are not limited to device identifiers, but it shouldn't be used for the public (only for your company or the employees of a specific company).
Each profile type must be registered with a certificate and they both are required during the code signing process. You can only install your application after the binary is signed properly. If the certificate is expired or you don't have the corresponding private key you won't be able to sign the app. Also if the provisioning profile is invalid, or if it doesn't contain your device identifier (see below) you won't be able to launch your app. 📱
The anatomy of a provisioning profile
Every single provisioning profile contains the following things:
- app identifier
- unique device identifiers (optional)
An app identifier can be registered through the developer portal by providing a bundle identifier search string. It can be an explicit one or a wildcard app id. Apple is going to create it from your team id and the bundle id. It's used to uniquely identify your app during the provisioning process.
Quick note: A bundle id is just a unique identifier under your developer account, but the app identifier is a widely used unique id for the entire App Store ecosystem. Usually, you should use a reverse domain notation when you create a bundle id.
The team section is just basic information about your developer team. If you are part of multiple developer teams, the build system has to find the right one for your provisioning profile during the code signing process.
Capabilities are (cloud-based) services and features. You can enable them from Xcode. Some of them need to be configured inside the developer portal under the App IDs section. For example, the Push notifications capability requires additional certificates and entitlements need to be added to your application.
Entitlements are simple configurations for accessing various services, such as iCloud storage, Push Notifications, Apple Pay and so on. It's a plist file inside your application bundle. You don't really have to worry about it too much, Xcode can normally take care of managing entitlements.
Certificates are used during the build process to sign the app. Every certificate has an associated private key component. In order to code sign the binary, you'll need the private key in your local keychain. Certificates can expire too, so you have to renew them every year or you won't be able to sign apps anymore. 🙅♂️
Unique device identifiers can be embedded into a provisioning profile. If you are trying to run a test version of your app on a real device you'll need to register your test devices' UUID. You can do it manually inside the developer portal or if you prefer Xcode it can also do the job for you. It doesn't matter which method you choose, but if you add a new device to the developer portal, you also have to re-generate the provisioning profile.
Expiration and invalidation
Both provisioning profiles and certificates do expire. If a profile expires, the app will fail to launch. You have to renew the profile, rebuild, resign and reinstall the application on the desired device if you'd like to continue to use it.
With the exception of an in-house distribution profile, all of the profiles expire in a year from the date of the creation of the profile. This means that the profiles must be re-generated yearly to keep distributing apps to devices or the App Store. ⌛️
Ad-hoc profiles have longer expiry dates. Also, if your application is submitted to the App Store, don't worry too much, you can install it any time. Distribution profiles do expire, but that only affects your code signing workflow.
However, there is one thing that can happen with your app in the App Store. If you break a rule Apple can revoke your signing certificate so you won't be able to submit apps anymore. They can also remove your application from the store.
If a certificate expires or gets revoked, the associated profiles will be invalid too. You can always check the status of your provisioning profile inside the developer portal.
What could go wrong?
Nowadays, you don't have to create provisioning profiles by yourself: you just need to connect your developer account under Xcode's preferences. If you are ready, you can safely enable the automatic code signing feature under the target, so Xcode can take care of the rest, but you should note that sometimes things can get messed up. 🤪
You can always use the developer portal to double check everything. Here is a quick list of the most common problems that can occur.
- you have a valid certificate (keychain + developer portal)
- the certificate has an associated private key (keychain)
- an App ID for your bundle id exists (developer portal)
- all the capabilities are set up and ready to use (Xcode + developer portal)
- the entitlements are ready to use (Xcode)
- the physical test device id is registered (developer portal)
- the provisioning profile is valid (developer portal)
- the provisioning profile contains the certificate and the device ids
How do you check the last one? Well, let me explain this briefly.
Checking what's inside a provisioning profile
The provisioning profiles are automatically downloaded by Xcode and stored under the ~/Library/MobileDevice/Provisioning Profiles directory. If you navigate to this folder you'll see a bunch of randomly named files. That ain't gonna help too much. 😅
There are two amazing QuickLook plugins, which will let you inspect the entire content of a provisioning profile directly from Finder. I really love this approach, because these plugins give me even more details than Xcode itself.
Let me sum up everything one more time really quickly. ⚡️
If you want to run an application on a physical device you have to configure a valid provisioning profile. You can obtain a profile from the developer portal. That profile, later on during the build process, will be embedded directly into the app bundle, plus the app is going to be code signed by using your developer credentials.
If you try to launch the app on the device, first the provisioning profile is going to be checked and if it doesn't match the required criteria your app won't run at all. If you are lucky enough and everything was ok, your app will launch just fine.
This whole process above is called provisioning. I hope you enjoyed this article. Next time I'll write about code signing and how to resolve code signing issues. 😉