iOS Certificates and Provisioning Profiles with Expo
By Mehdi Azizi
Published , 9 min
The certificate proves who signs your app. The provisioning profile says which app and which iPhones. With Expo, EAS creates and renews both for you.
An iOS developer certificate proves who signed your app. The provisioning profile ties that certificate to one specific app and says where it's allowed to run. With Expo, you almost never have to create them by hand: EAS creates them, stores them and renews them when you start a build.
It still helps to know what each file does. The day a build won't install or an upload gets stuck, that knowledge saves you a full day. This guide covers the four pieces, how long they last, Apple's limits and the typical errors, with the fix for each one.
I publish my iOS apps with Expo and EAS, including Solys and TradaZen. The full process is in publishing an iOS app without a Mac. Here, we look under the hood of code signing.
Why Apple requires a signature
An iOS app has to be signed to install on an iPhone or to be sent to App Store Connect. The signature guarantees the app comes from a developer Apple knows and that nobody has modified it since.
For the App Store, one detail is reassuring. According to Apple's technical note TN3161, the App Store checks that your distribution certificate is valid at upload, then re-signs the app, which then no longer depends on your certificate's expiration date. So your certificates need to be valid when you upload, not for the whole life of the app.
The four pieces you need to know
Expo's documentation on credentials lists three for iOS: the distribution certificate, the profiles and the push notification key. I'm adding the App ID, without which no profile can exist.
The distribution certificate
This is your developer signature. Apple's help on certificates separates two families:
- Apple Development is for running your app on your devices during development. It belongs to one person.
- Apple Distribution is for distributing to designated test devices or uploading to App Store Connect. It belongs to the team, and only the Account Holder or an Admin can create it.
The distribution certificate isn't tied to any specific app: the same one signs all your apps. It comes with a private key, and that key is what lets you sign. According to TN3161, an Apple certificate is generally valid for one year from its creation.
The App ID
The App ID identifies your app inside a profile. It uses your bundle identifier, for example com.example.myapp (a made-up example). According to Apple's help, it also carries the list of allowed capabilities: push notifications, App Groups, Sign in with Apple…
With Expo, it's the ios.bundleIdentifier field in your config. Pick it once and for all: it has to be identical everywhere, in your config and in App Store Connect. The App ID doesn't expire. And according to Expo's docs on iOS capabilities, EAS syncs its capabilities with your config on every build.
The provisioning profile
The profile connects everything. It contains an App ID, a certificate and, depending on its type, a list of allowed devices. Three types matter to you:
- Development: your test app on your registered devices.
- Ad hoc: a build that can be installed on a specific list of devices, each identified by its UDID. This is EAS "internal distribution."
- App Store: for App Store Connect and TestFlight. It contains no device list, as technote TN3125 explains.
Every profile has an expiration date: generally no more than one year according to Apple, 12 months according to Expo.
The push notification key (APNs)
The APNs key lets your server, or Expo's, send notifications to your app. It's a .p8 file you can only download once: Apple doesn't keep it in your account. One key works for all your apps, and it never expires.
The summary table
| Piece | Used for | Lifetime | Who handles it with Expo |
|---|---|---|---|
| Distribution certificate | Signing your builds | Generally one year | EAS, after you sign in |
| App ID | Identifying your app | No expiration | You, then EAS |
| App Store profile | Uploading to Apple | Up to 12 months | EAS |
| Ad hoc profile | Installing on iPhones | Up to 12 months | EAS and your devices |
| APNs push key | Sending notifications | No expiration | EAS or you |
| Free account profile | Testing through Xcode | 7 days | Xcode, not EAS |
"You, then EAS": you choose the bundle identifier, EAS handles the capabilities. "EAS and your devices": you register each test iPhone, EAS builds the profile. The last row is about the free Apple account: according to Apple's help on accounts, its profiles expire 7 days after they're created.
Apple's limits you need to know
- Distribution certificates: very few per account. Apple's help mentions one per distribution type per team, Expo's table a limit of 2. Remember the rule: don't create a new certificate for every build or on every computer.
- APNs keys: 2 per account max, according to Expo.
- Profiles: no limit, according to Expo.
- Devices: up to 100 per product family per membership year, according to Apple's help on devices. Disabling a device doesn't free up a slot. The count resets to 100 at the start of the next membership year, if you remove the devices.
What EAS does for you
According to Expo's page on managed credentials, your first iOS build offers to generate whatever is missing. You sign in to your Apple Developer account, EAS creates the distribution certificate, the profile and the push key, then stores them on its servers. Later builds reuse them.
Three useful points:
- Your Apple password stays on your machine. Expo's security page states that it's not sent to their servers, and that stored credentials are encrypted.
eas credentialsshows you everything: certificate, profiles, push key. The command also lets you replace or remove them.- Deleting in EAS doesn't delete at Apple. To free up a slot, you need to revoke in the Apple portal.
You can also stay in control with local credentials: a credentials.json file points to your certificate (.p12) and your profile (.mobileprovision). Expo asks you to add these files to .gitignore. Same rule as for API keys in an Expo app: a secret never goes into the repo.
Typical errors and how to fix them
Expired profile
An ad hoc build embeds its profile: once it expires, the app won't open on your test iPhones anymore. On the App Store, though, Expo confirms that expiration has no effect on the app in production. The fix: run a new build. EAS generates a new profile, or you do it yourself with eas credentials. Then reinstall the new build on your devices.
Don't confuse this with TestFlight: a TestFlight build expires after 90 days, whatever your certificate. Details are in TestFlight for testing your iPhone app.
Expired or revoked certificate
Apple is clear: if your membership is valid, your apps already on the App Store aren't affected. However, you can no longer upload a build signed with that certificate. A build that's uploaded but not yet submitted can be marked Invalid Binary if its certificate was revoked. And profiles that contain a revoked certificate become invalid.
The fix: create a new certificate from eas credentials or on your next build, then let EAS redo the profiles. And never revoke a working certificate out of reflex.
Device missing from the ad hoc profile
The install link works for you, but not on a tester's iPhone. The cause: Expo's docs on internal distribution explain that only devices included in the profile at build time can install the app.
The fix:
- Register the device with
eas device:create. - Run a new build in interactive mode, signed in to your Apple account, so EAS updates the profile. Or re-sign the existing build with
eas build:resign, without recompiling everything. - In continuous integration, non-interactive mode reuses the profile without updating its list. Add the
--refresh-ad-hoc-provisioning-profileflag.
On a brand-new or just-renewed account, Apple can take 24 to 72 hours to process a new device. So the first build that includes it may fail: wait, then try again.
Certificate limit reached
Apple refuses to create a new distribution certificate. Often, old certificates are lying around: created from Xcode on another Mac or by another build service. Reuse the existing certificate if you have its .p12 file. Otherwise, revoke the one you no longer use in the Apple portal. A revocation doesn't affect your apps already live, but it invalidates the profiles that contained it.
"Provisioning profile doesn't include signing certificate"
This Xcode message means the profile doesn't contain the certificate whose private key is on your machine. Typical cause: mixing Xcode's automatic signing with EAS credentials. Pick a single source of truth: EAS builds with managed credentials, or local credentials, but not both.
Notifications cut off after revoking a key
If you revoke your APNs key, Expo warns that every app using it stops receiving notifications. Create a new key and upload it with eas credentials. Your users' Expo Push tokens don't change.
Capability added, profile invalid
Enabling a service like push notifications or App Groups makes the profile invalid: you need to regenerate it. With EAS, capabilities sync on every build. If the profile still gets rejected, eas credentials lets you generate a new one.
What comes after signing
A signed build is just one step. The listing, screenshots, privacy and submitting for review are all covered in publishing an app on the App Store. If you don't have your membership yet, start with the Apple developer account. And to understand why I recommend Expo to beginners, read React Native and Expo for a mobile app.
If you're preparing your first release
Before your first upload, take the free diagnostic: it tells you what's actually blocking your project and sends you my anti-rejection checklist for Apple.
To build the app, wire up subscriptions and publish it without fighting code signing, the iOS & Android Kit walks you through the four-step process with the starter code from my apps, at your own pace.
Frequently asked questions
What is a provisioning profile?
It's the file that allows your app to run or to be sent to Apple. It ties together an App ID, a certificate and, depending on its type, a list of devices. An App Store profile contains no devices, an ad hoc profile lists a few.
Is the iOS developer certificate free?
It has no separate price: the distribution certificate is included in the Apple Developer Program, at $99 a year. With a free Apple account, Xcode lets you test on 3 devices at most, but profiles expire after 7 days and publishing is impossible.
How long does an Apple distribution certificate last?
Generally one year from its creation, according to Apple. Provisioning profiles also last 12 months at most. The push notification key, on the other hand, never expires.
What happens if my distribution certificate expires?
Nothing for your apps already on the App Store, as long as your membership is valid. You just can't upload a new build signed with that certificate anymore. With EAS, a new certificate gets created on your next build or with eas credentials.
Do I need a Mac to create an iOS certificate?
No, if you use EAS. You sign in to your Apple account from the command line, and EAS generates the certificate and the profile, on Windows or Linux. Without EAS, the classic method goes through Xcode or Keychain Access on a Mac.
How many devices can an ad hoc profile contain?
Your account can register up to 100 iPhones per membership year, and the same number for each other device family. A disabled device still counts. To test with more people, use TestFlight.

