Explain code signing, certificates and provisioning profiles.
TL;DR
iOS only runs code signed by a trusted identity. Three pieces work together:
- Certificate (+ private key): proves who signed the app. Development or Distribution.
- App ID: which app (bundle identifier) and which capabilities it may use.
- Provisioning profile: ties it all together: certificate + App ID + entitlements (+ device list for development and ad hoc).
When the app is installed or launched, iOS checks the signature and the profile. Any mismatch means it will not install or run.
The pieces
Signing certificate ─┐
App ID (bundle ID) ─┼──> Provisioning profile ──> embedded in the .app
Entitlements ─┤
Devices (dev/ad hoc) ─┘Certificate and private key
- You create a key pair. Apple signs your public key and gives you a certificate.
- The private key stays in your Mac's Keychain. Without it, the certificate is useless.
- Losing it means making a new certificate. Sharing it badly is a security risk.
| Certificate | Used for |
|---|---|
| Apple Development | Running on your own test devices |
| Apple Distribution | TestFlight, App Store, ad hoc, enterprise builds |
Entitlements
Entitlements are keys that grant special abilities, such as push notifications, App Groups, iCloud, Associated Domains or Keychain sharing.
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:example.com</string>
</array>The entitlements in the app must be allowed by the profile. Otherwise signing or installation fails.
Provisioning profile types
| Type | Devices | Use |
|---|---|---|
| Development | Listed devices only | Daily development |
| Ad Hoc | Up to 100 devices per device type per year | Testing outside TestFlight |
| App Store | Any (through Apple) | TestFlight and App Store |
| Enterprise (In-House) | Any device in the organization | Internal apps, needs the Enterprise program |
Automatic vs manual signing
Automatic signing (Xcode manages it): Xcode creates certificates, App IDs and profiles for you. Great for small teams and local development.
Manual signing: you pick the exact profile per configuration. Common on CI and in big teams.
CODE_SIGN_STYLE = Manual
DEVELOPMENT_TEAM = ABCDE12345
CODE_SIGN_IDENTITY = Apple Distribution
PROVISIONING_PROFILE_SPECIFIER = MyApp AppStoreSigning on CI
The CI machine needs the certificate, its private key and the profile. Common options:
- fastlane match: stores encrypted certificates and profiles in a private Git repo or cloud storage. Every machine gets the same ones.
- App Store Connect API key +
xcodebuild -allowProvisioningUpdates: cloud-managed signing, no manual export of certificates. - Xcode Cloud: signing is handled for you.
Extensions need their own setup
A widget, share extension or notification service extension has its own bundle ID, App ID and profile. Their bundle IDs must start with the app's bundle ID (for example com.example.app.widget).
Debugging signing errors
# What entitlements are in a built app?
codesign -d --entitlements - MyApp.app
# What does a profile contain?
security cms -D -i embedded.mobileprovision
# Is the signature valid?
codesign --verify --deep --strict --verbose=2 MyApp.appCommon errors:
- "No profiles for 'com.example.app' were found": no matching profile for this bundle ID and certificate.
- "Provisioning profile doesn't include the X entitlement": turn on the capability for the App ID, then regenerate the profile.
- "Device not registered": add the device UDID and refresh the development profile.
Common follow-up questions
- What happens when a distribution certificate expires? Apps already on the App Store keep working. You need a new certificate to upload new builds. Ad hoc and enterprise builds stop working when their profile or certificate expires.
- Why does push work in debug but not in TestFlight?
aps-environmentisdevelopmentvsproduction, and the server must use the matching APNs environment. - What is the Team ID? A 10-character ID for your developer account. It prefixes App IDs and appears in the AASA file.
- Can two apps share Keychain data? Yes, with the same Team ID and a shared Keychain Access Group entitlement.