Note on Apple code signing (mobile iOS apps) for newcomers

You want to start developing mobile apps for iOS (native or with ANY framework). You don’t want to mess with bureaucracy and procedures. This time, however, you can’t escape.

In this blog post, I’ll explain how the Apple code signing works for mobile iOS apps, at least from an “app developer” point of view. I hope this will help you understand a bit of this process because you need to understand at least some fundamentals before starting.

For a detailed (and boring) explanation you can refer to the official Apple documentation.

This assumes that you know some basic concepts of PKI, certificates, public and private keys.

Why?

I won’t bother you with political views, pro/cons about choices, etc. I’ll try to explain one of the reasons why this procedure exists.

One is “security”. The code signing guarantees that only Apple-approved apps (or, at least, Apple-approved developers) can run on their iOS (and, more recently, macOS). So malware apps should either try to get approval from Apple or try to break the whole system (both are very rare events).

This system is not the best in terms of “user experience”. You can see why. Also, several alternatives don’t require all these limits to the user freedom of installing whatever he/she likes.

Glossary

Before starting, we need to define a short glossary:

You can generate new certificates and provisioning profiles using the wizard (and the Keychain app in your macOS) in the “Certificates” web page of the App Store Connect. In addition, you can generate provisioning profiles and manage the list of allowed devices (for development) using the same web UI.

How?

It’s is pretty simple. The code is digitally signed, and the phone runs only digitally signed apps. That’s it.

How this code is digitally signed? There are three different situations:

The way this works for Enterprise programs is quite similar. So, for now, I won’t cover it (maybe in a dedicated blog post?).

App Store and TestFlight (public distribution)

Apps are signed with a certificate from Apple. The signing occurs when the app is published in the App Store Connect (the developer “panel” for the App Store). Then, at install/run time, the iOS system checks that the app’s certificate is signed by Apple certification authorities: if so, the app can run.

This mechanism is why you can’t “simply” load an app in the iPhone and launch it like you are used to in PCs or iMacs. You need to obtain this certificate first. And to do this, your app needs to pass thru the App Store Connect system (which includes automatic and manual checks to the app). The signing part is hidden, so you don’t need to care about it.

There are two other things that you need to take into consideration: the Distribution certificate and the Provisioning profile.

The Distribution certificate is needed because you need to sign the app when you send it in the App Store Connect for approval. The App Store Connect won’t accept binary code that is not signed by a developer.

The Provisioning profile: Xcode will need this (together with the Distribution certificate) to sign your app for upload, and the App Store Connect will need this to verify that you’re allowed to do so.

Xcode (e.g. you build and load your application inside your iPhone for testing)

Apps are signed using your development certificate, which in turns is signed by Apple. The iOS system checks that the certificate is valid and that the certificate, the app ID and the iPhone unique ID are in the provisioning profile.

So you need a developer certificate in this mode.

The significant change here (in respect to the distribution) is in the mobile provisioning profile itself. When using apps in development mode, the provisioning profile must also contain the list of device UUIDs allowed for that specific app. This means that you need to authorize your iPhone/iPad by providing the UUID to the Certificates system, which will include it in the provisioning profile.

This is the reason why you can’t build an app in “development” mode and redistribute the IPA (e.g. the app “bundle”). I mean, you can do it, however only listed devices can install it (and the list is small, something like 200 devices).

So what I need to do?

When you start developing for iOS, you don’t need any of this if you use only the simulator. However, if you want to test your app on an actual device (which I strongly suggest), you need to:

Then, when your app is ready for TestFlight or even for distribution, you need also: