iOS Code Signing Explained: Certificates, Profiles and Keys

By the jocapps team6 min read

Short answer

iOS code signing proves to Apple and to the device that an app comes from a known developer and has not been modified. It needs four things that must match: a signing certificate with its private key, an App ID (bundle identifier), a provisioning profile that ties them together with entitlements, and, for automated uploads, an App Store Connect API key.

Most first-time iOS releases do not fail because of the code. They fail at the signing step, with an error message that names a certificate, a profile or an entitlement and assumes you already know how those relate. This guide explains each piece, how they connect, and how to diagnose the errors you are most likely to see in Xcode or a CI pipeline.

The five building blocks, defined

Think of code signing as a chain of trust. Every link has to be present and has to point at the next one.

  • Signing certificate: an identity issued by Apple to your developer account. In practice there are two you care about: Apple Development (for running builds on test devices) and Apple Distribution (for TestFlight and App Store builds). The certificate is public; what makes it useful is the matching private key, which lives in the keychain of the Mac that created the certificate request.
  • App ID / bundle identifier: the reverse-DNS name of your app, such as com.example.notes. It is registered in your developer account and carries the list of enabled capabilities (push notifications, Sign in with Apple, App Groups, associated domains and so on).
  • Entitlements: the capabilities your binary claims at runtime. They are declared in an .entitlements file in the Xcode project and must be a subset of what the App ID allows.
  • Provisioning profile: a signed file from Apple that bundles an App ID, one or more certificates, the allowed entitlements and, for development and ad hoc profiles, a list of device UDIDs. It is the document that says "this certificate may sign this app with these capabilities".
  • Keys (.p8 files): separate from certificates. An App Store Connect API key lets tools like Fastlane, Xcode Cloud or a CI runner upload builds and manage profiles without a personal Apple ID login. An APNs authentication key is used by your server to send push notifications. Neither signs your app binary.

How the pieces fit together at build time

  1. Xcode (or xcodebuild) reads the bundle identifier and the entitlements file of your target.
  2. It looks for a provisioning profile whose App ID matches the bundle identifier and whose entitlements cover the ones in your file.
  3. It checks that the profile includes a certificate for which the private key is available in the current keychain.
  4. It signs every executable part of the app (the main binary, frameworks and app extensions) with that identity and embeds the profile.
  5. When you upload, App Store Connect validates the signature, the profile type and the entitlements again before the build reaches processing.

Each app extension (widgets, notification service extension, share extension) has its own bundle identifier and needs its own matching profile. Forgetting this is one of the most frequent reasons a build signs fine locally but fails during export or upload.

Profile types and when each is used

Profile typeCertificateDevicesTypical use
DevelopmentApple DevelopmentRegistered UDIDs onlyRunning debug builds on your own and your team's devices
Ad HocApple DistributionRegistered UDIDs only (limited per year)Sharing a release-like build with a small, known group outside TestFlight
App Store Connect (App Store)Apple DistributionAny device, via TestFlight or the App StoreEverything you upload to App Store Connect
In-House (Enterprise)Enterprise distributionEmployees of the enrolled organizationInternal apps under the separate Apple Developer Enterprise Program, which has its own eligibility rules

For a normal App Store release you only need one Apple Distribution certificate per team and one App Store profile per bundle identifier.

Automatic vs. manual signing vs. a shared signing repository

There are three common ways to manage all of this, and the right one depends mostly on how many machines build your app.

  • Xcode automatic signing: Xcode creates and renews certificates and profiles for you. Ideal for a solo developer on one Mac. It becomes fragile when several people or a CI server each create their own certificates, because you end up with multiple identities and profiles that silently replace each other.
  • Manual signing: you create certificates and profiles in the developer portal, download them and select them explicitly in the target settings. Predictable, but someone has to remember renewals and distribute the private key securely.
  • Shared signing repository (for example Fastlane match): one encrypted store (a private Git repo or a cloud bucket) holds the certificates, private keys and profiles. Every developer machine and CI runner pulls the same identity read-only. This is the most robust option for teams and for pipelines where coding agents push code but should never touch signing material.

If you use Xcode Cloud or Expo's EAS Build, those services can manage signing credentials for you. Check their current documentation for how credentials are stored and who on your team can access them.

Error messages and what they usually mean

Error (paraphrased)Likely causeFix
No signing certificate "Apple Distribution" foundThe certificate exists in the portal but the private key is not on this machineImport the .p12 (certificate plus key) or pull it from your shared signing store
Provisioning profile doesn't include signing certificateThe profile was generated before the current certificate was createdRegenerate the profile with the active certificate selected
Profile doesn't support capability or doesn't include entitlementA capability was added in Xcode but not enabled on the App IDEnable it on the App ID, then regenerate the profile
Signing works locally, fails on CI with a keychain errorCI keychain locked or not in the search listCreate a temporary keychain in the job, unlock it and set its partition list before import
Upload rejected for an extensionExtension signed with a development profile or a mismatched teamGive every target an App Store profile from the same team
Build expired in TestFlight earlier than expectedNormal behavior: TestFlight builds expire after a fixed periodUpload a new build; this is unrelated to certificate expiry

A hygiene checklist for teams

  • Enroll as an organization so certificates belong to the company, not to an individual. Our guide to the Apple Developer account for companies covers roles and access.
  • Keep exactly one active Apple Distribution certificate and document who can revoke it. Revoking does not remove live apps from the App Store, but it breaks every profile and pipeline that depends on it.
  • Put renewal dates for certificates and profiles in a shared calendar. Both expire, typically after a year.
  • Store private keys and .p8 files only in a secrets manager or an encrypted signing repository, never in the app repository and never in prompts or chat logs with an AI assistant.
  • Use an App Store Connect API key with the narrowest role that still allows uploads for CI.
  • Write the signing setup into your project README so the next person (or agent) does not reinvent it. The same applies to the pipeline itself; see CI/CD for AI-generated mobile apps and the Fastlane setup for Claude Code projects.

When to hand signing off

Signing is a one-time setup with recurring maintenance, and it is unforgiving: a wrong profile type or a missing extension profile costs a full build-and-upload cycle each time. If you would rather spend that time on the product, appsubmitter.io sets up signing and CI/CD inside your own Apple and Google developer accounts and handles the submission, so the certificates stay yours. Either way, run through the App Store submission checklist before your first upload; signing is only one of the gates.

Apple's own reference for all of the above is the Apple Developer Documentation and the Certificates, Identifiers & Profiles section of your developer account.

Frequently asked questions

Do I need a Mac to sign an iOS app?

Building and signing with Xcode requires macOS, either your own Mac or a cloud macOS runner. Hosted services such as Xcode Cloud or EAS Build run on Apple hardware for you.

What happens to my live app if my distribution certificate expires?

Apps already on the App Store keep working. You only need a valid certificate and profile to sign and upload new builds.

Is the App Store Connect API key the same as a signing certificate?

No. The API key authenticates tools to App Store Connect for uploads and account automation. The certificate and its private key sign the app binary itself.

Why does each app extension need its own provisioning profile?

Every extension has its own bundle identifier and entitlements, and iOS validates each signed bundle separately, so each needs a profile matching its own App ID.

Can an AI coding agent manage code signing for me?

An agent can write the pipeline configuration, but it should never hold private keys. Keep signing material in a secrets store that the CI job reads, and let the agent work only on code and config.

Want a second opinion on your project?

Book a free 30-minute call with our team. We look at your idea, prototype or app and tell you honestly which route makes sense – whether you work with us or not.

Book a free call or write to [email protected]