How do provisioning profiles actually *work* in iOS and Xcode? - ios

I am trying to understand signing identities and provisioning profiles in iOS development. (Let us focus on development for now and not distribution via app-store. One issue at a time)
Note: I'm not looking for a how-to, but rather a general conceptual overview. In fact, Xcode seems to have taken care of all of it for me in some mysterious fashion, and things seem to work, but I want to understand what it actually did, and how it all fits together.
Signing Identities
I think I understand signing identities. Here is how I think it works (let me know if I'm mistaken):
Apple has decided that users should not be able to run any random application on iOS and part of the technology it has used to implement this selectiveness is code signing.
Code signing is process of encrypting a hash of the binary with a private key and including the encrypted hash along with the binary. This is now a signed binary. Also included along with the binary is a certificate signed by Apple with includes the public key part of the key pair and effectively says that a binary signed with the private key that corresponds to the public key in the certificate is approved by Apple to run.
When iOS is asked to launch an app, it looks to see if the certificate is valid and that the app is indeed signed by the private key corresponding to the public key in the certificate. If everything is good, it launches the app.
Provisioning Profiles
This is where my understanding of things start to break down. Here is what (I think) I know:
Code signing as described above can't be the whole story in the implementation of selectiveness. As a developer I can get a key pair and a certificate from Apple and I can sign my code with it. But that actually won't run as-is on an iOS device, as indeed it should not. If it did, then all one needs to build an app that runs on every iOS device is a developer account, and anyone can get that (well, anyone that can afford $100 a year).
What explains this is that the certificate I get from Apple is a developer certificate and that doesn't actually tell iOS that the app signed with the (private key corresponding to the) certificate is approved to run. It simply says that it is built by a valid developer. In order for iOS to decide that it is OK to run, it needs some additional information. I believe that information is what is stored in development provisioning profile.
The profile seems to associate developers, applications ids, and devices, saying in effect that applications with the id specified in the profile, built by the developers specified in the profile, are ok to run in the devices specified by the profile.
The Actual Questions
What I don't understand is that the provisioning profile must:
Be available on the device. iOS on the device is the entity that is in the end making the decision whether to run the app or not, so it must look through the provisioning profiles to decide. How do the profiles get to the device?
Be certified by Apple. If the profile is not certified by Apple, then I can associate any app I want to my developer certificate and get it to run. How does that certification happen? Or is there some other mechanism at work?

Related

Why do you need a IOS Developer Certificate to run IOS app on Device?

A bit of a beginner to IOS. I am trying to understand Certificates, Provisioning Profiles, Code Signing Identities and frankly, it is a bit difficult for me to understand the developer docs.
I understand that the Certificate is a security mechanism for Apple to ensure that no one has tampered with your code, with a Public and Private Key (for you to sign off on your application). This makes sense when you submit your app to the app store or for adhoc testing, as Apple wants to make sure this is the final version that you would like to submit (IOS Distribution Certificate). But how does that apply for IOS Developer Certificate?
From what I understand, IOS Developer Certificate is used to limit who can run your application and on what devices it can be run on.
Development certificate is mostly used while application is being developed and it limits number of number devices (100) on which app can be installed. Also distribution certificate won't let you debug the application while installing from Xcode and disconnect you. It is primarily for signing app store build. There's no difference in the certificates themselves other than the separation Apple does for you.
Code signing your app assures users that it is from a known source and the app hasn’t been modified since it was last signed.
You can refer Code Signing, if describes how code signing works in detail. It will help you understand why code signing is required.

valid iOS Distribution Cetificate - developer name change

Here's how I've been led to this path.
I started on a macbook, with a standard developer account. Submitted a few applications. Then moved to an iMac, same developer account. Submitted a few applications.
Now, my developer account is a company account i.e, I got the name changed to my company name. However, now I cannot submit to the app store. I get your account already has a valid iOS Distribution Certificate
I cannot get past this hurdle!
I'll now try and explain which profiles and signing identities I have in my developer account.
Certificates
Company name - iOS Distribution
My Old account name and/or my actual name - iOS Development
App IDs
Application Name - Correct bundle identifier
Provisioning Profiles
iOSTeam Provisioning Profile: App-Name - iOS Development
App Name - iOS Distribution - Active ( correct app id and correct certification for distribution )
All of these certificates are locally in my keychain.
However, I cannot get it to work. Some help would be greatly appreciated, I'm having an absolute nightmare.
The certificate is just used to prove that you are the person who (signed and) submitted the app.
Apple re-signs your app with their credentials before it appears on the store. You can be assured that revoking a certificate won't invalidate any previous submissions for this reason.
The issue right now is that Xcode and/or keychain are likely affected by (or using) conflicted (or old) details, and Xcode doesn't recognize that something has changed, or cannot replace the old data with the current data.
You should revoke your certificate(s), delete them from Xcode and keychain, then let Xcode generate a new one.
Otherwise, those old keys will linger in Xcode and keychain and be a point of confusion, both now, and down the road.
I realize it seems like an ominous thing to do, but if there were dire consequences, Apple would clearly be warning you, instead of letting you simply revoke and be reissued a new certificate.
Solution in my case.
I deleted all old certificates/keys, revoked my distribution profile from the members centre ( so I didn't have any ) Then proceeded to xCode>Accounts>View Info> + > distribution profile and it generated me a new one.
This has now allowed me to submit via the app store and remove the very vague error.

Submitting Ad-hoc app to Appstore / iTunesConnect

I know how to sign an app with Appstore mobile provision, and how to re-sign an Adhoc-signed IPA with Appstore mobile provision. This is not my question.
My question is, can you submit Adhoc-signed IPA to Appstore / iTunesConnect, and have it pass Apple verification and eventually be distributed through Appstore. Why? So that I don't have to store a redundant Appstore-signed IPA along every Adhoc-signed release candidate IPA, and don't have to do the extra step of re-signing that requires a Mac machine.
When using Application Loader, it is able to find all the stupid little errors, like missing icons and launch images, but even when I upload Adhoc-signed IPA through Application Loader, it doesn't complain about non-appstore mobile provision (which is very easy to verify, just like icons).
I have also found out in my testing, that when you take an Appstore-signed IPA (which you are not supposed to be able to install on devices unless distributed through Appstore), it is possible to install it on testing devices, provided the device already has Adhoc provision profile on it (same AppID, same distribution cert).
So, this makes me think Apple just strips out mobile provision when distributing through Appstore.
There was a similar question (closed) from almost 3 years ago, but the OP never provided an answer if it had actually worked: Submitted app to appstore with adhoc profile.
I hope someone since then had actually tried with it confirmed results.
There are a few targeted inner questions within your main question, I'll call attention to each part as we go -- as always, I'll be happy to revise or clarify if I miss something. I suppose it is only a closely guarded secret because much of the reasoning for it working come back to cryptographic details as a function of the Public Key Infrastructure system that backs Apple's provisioning -- This stuff gets deep fast so it is considered by some to be [dark] magic. Hopefully this will shine some light on what is going on!
TL;DR Version
Yes you can, but it is technically an unsupported use case that may change at any time. This works because what information iTunes Connect chooses to validate does not include the single differentiating factor between an App Store and AdHoc distribution provisioning profile. Since this is technically not a permitted configuration, I'd advocate for at least having a backup plan since Apple may change iTunes Connect validation policy at any time breaking this submission edge case.
Now for the curious, the here is the rest of the story...
Can you submit Adhoc-signed IPA to Appstore / iTunesConnect, and have it pass Apple verification and eventually be distributed through Appstore[?]
As of this specific iteration of iTunesConnect and the Application Loader (4 Sept 2014 / Xcode 5.1.1), yes you can submit an AdHoc signed build and have it accepted through the pipeline. The eagle-eyed reader will note that my 'Yes' comes with a built-in escape hatch -- Because of the data encoded in AdHoc vs App Store provisioning profiles is nearly identical coupled with what parts of these files iTunesConnect is actually using for validation, an AdHoc provisioning profile presents to the delivery pipeline in the same manner as the AppStore version of the same app.
Should the provisioning format change between AdHoc and App Store files to explicitly differentiate the two types of Distribution provisioning profiles or should Apple iTunesConnect engineers change server-side validation rules, it is distinctly possible that this undocumented behavior will stop working. Of course we all know that we are supposed to use the App Store provisioning profile, as per Developer documentation in the App Distribution Guide > Submitting Your App > About Store Provisioning Profiles (https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html#//apple_ref/doc/uid/TP40012582-CH9-SW32) [emphasis added]:
A store distribution provisioning profile contains a single App ID that matches one or more of your apps, and a distribution certificate. For iOS apps, you need a store provisioning profile to submit your app.
...but this other avenue works for now. If you do choose to use this avenue, you just need to be aware that it is not the documented behavior and thus would be subject to change at any point in time, likely without advanced notice. Since it is skirting the edges of submission requirements it would probably be good to at least have a backup plan setup for the case of Apple changing provisioning or iTC validation requirements -- Murphy's law would dictate that these validation changes would happen at the most inopportune time.
Stepping off the 'Best Practice' Soapbox and turning to the technical side of things...
Why [does this work]?
As you may or may not know, provisioning profiles are composed of exactly 1 appId, one or more signing certificates, and zero or more test devices.
Related Reading: I've got a longer answer to What are code signing identities? that speaks in more detail to the parts of the codesign process.
In this case the question is 'why do AdHoc profiles work when the documentation says you need to have an App Store profile?'
The guts of a provisioning profile contain a cryptographically signed .plist that includes the information identified above, plus some additional metadata. On an OS X machine you can open Terminal and run:
security cms -D -i path/to/AdHoc.mobileprovision
...and in a separate Terminal window run the App Store profile equivalent:
security cms -D -i path/to/AppStore.mobileprovison
These commands will dump out the plist portion of the provisioning profile to their respective Terminal windows. When you scroll through the contents of both windows you will note that the following sections are identical:
AppIDName
AppliationIdentifierPrefix
DeveloperCertificates
Entitlements
TeamIdentifier
Version
The profile's metadata are different, but those are entirely expected differences that only matter for validating profile validity, or for humans interrogating the profile:
CreationDate
ExpirationDate
Name
TimeToLive
UUID
The salient points to take away are:
The DeveloperCertificates blocks are identical between both profiles.
The AdHoc profile only adds information (ProvisionedDevices) to the structure and format of the App Store profile.
The contents of the DeveloperCertificates array is the DER encoded X.509 iPhone Distribution Certificate -- The exact same as the one in your keychain. Is is important to note that this DER data is only the public portion of your Distribution certificate public-private keypair, and it can only be used by others to authenticate the application's signature came from you -- It can not be used to resign a binary as you.
If you paste the contents of DeveloperCertificates:Array:Data element into an ASN.1 decoder (http://lapo.it/asn1js/) and compare the elements of the output to the information encoded in the Distribution certificate included in the Keychain, you'll find that it is an exact copy of the public Distribution certificate you downloaded from Apple after submitting your Certificate Signing Request though the Certificates, Identifiers, and Profiles tool.
Because both the AdHoc and App Store provisioning profiles use the same public key certificate as their signing identity, they are inherently using the same private key when generating the application's signature. This means that the signature generated when signing with an AdHoc profile is functionally identical to one generated when signing with the App Store profile
When Apple performs a signature validation on iTunes Connect during the submission process, both and AdHoc signed cryptographic signature and an App Store signed cryptographic signature will successfully validate against the Distribution Certificate Apple has on file as both provisioning profiles are backed by the same Distribution Certificate.
So the signatures match, but why doesn't the extra information in AdHoc profiles trip up the submission?
Your original question suggests that you have familiarity with iOS' app install policies. For the benefit of someone stumbling across this answer in the future I'll briefly summarize:
iOS operates on a 'deny-all unless specifically permitted' policy. That is, iOS assumes you are not allowed to install an app unless a specific 'grant' has been allowed. For devices coming from the App Store, the app's signature includes Apple's App Store identity for which iOS has a specific 'grant' privilege. AdHoc installs by default fall under the 'deny' policy and the ProvisionedDevices section of a Development or AdHoc profile are the specific 'grant' privileges. The app will install outside of the App Store if all of the following hold true:
The application's cryptographic signature is valid
The application's embedded provisioning profile's cryptographic signature is still valid (the profile hasn't been tampered with)
The application's embedded provisioning profile's ExpirationDate hasn't passed and the current time isn't before the CreationDate
The embedded profile or a profile installed to the device match the AppId being proposed for installation.
The embedded profile or a profile installed to the device contain an entry in ProvisionedDevices that exactly match the device's UDID.
As we saw above, the app identity and signing information is identical between an App Store profile and and Ad Hoc profile -- the addition of ProvisionedDevices serves only to add these 'grant' privileges for an external (outside of App Store) distribution mechanism. It turns out that iTunes Connect / Application Loader validation is currently only validating that a Distribution profile was used for the app's signature, not that the profile that was used was an App Store profile instead of an AdHoc profile.
This boils down to the fact that the as of Version 1 (ala Version block in the plist) the only differentiating factor between AdHoc and App Store distribution profiles is the presence or absence of the ProvisionedDevices block. It turns out that as of today, this is not a detail that Apple looks for when interrogating the profile that was used, thus the binary passes the automated portions of app verification. They definitely do check that the AppId in the profile matches what the App claims, that the signing identity matches what was used to sign the binary, expiration dates, and any entitlements used match what is found in the automated scan of the app, in addition to the items you highlighted in your original question (version checks between iTunes Connect and the info.plist, iconography presence, iconography sizes, etc.)
Hypothetically, in a subsequent iTunes Connect / Application Loader update, they could start checking for the absence of this key in the embedded.mobileprovision profile that exists within the submitted binary and auto-reject the submission on the grounds that an App Store profile was not used. Similarly, if the provisioning profile format was updated (ex. Version=2) they could add a new element that explicitly calls out the type of profile and auto-reject if it isn't an App Store type. It could perhaps look like this:
<key>ProfileType</key>
<integer>1</integer>
Where the integer value could be 1, 2 or, 3 depending on the type of profile in use, consistent with the formats used in things like Info.plist for identifying supported device families (iPhone-only, iPad-only, or Universal). This would clarify other questions that have been asked about identifying the type of build.
Related Reading:
How to detect that a provisioning profile is for development or distribution, programmatically
Check if app is ad-hoc|dev|app-store build at run time
So, this makes me think Apple just strips out mobile provision when distributing through Appstore.
Yes they do! If you look at archived versions of the apps you submitted you'll find that the contents of the app contain embedded.mobileprovision -- if you then go download the same version from the App Store, you'll find that file missing. Apple only uses embedded.mobileprovision to verify the contents of your app during the submission and review process. When the app is 'Processing for App Store' the final package is assembled and the embedded profile is removed.

Certificate identity 'iPhone Developer: ' appears more than once in the keychain. The codesign tool requires there only be one

Ok, I am completely pulling my hair out on this one.
Back in July I created a provisioning profile so I could test on my iPad.
Then at the end of August I tried submitting my first App to the iTunes Store. The process was a complete nightmare, and I struggled. A lot. In the end I found a tutorial with relatively recent information in it, and only by following it step by step could I actually get anywhere with this. Unfortunately the result of this was that I created a new provisioning profile.
Now when I try to test on my iPad I get the following error in Xcode:
Certificate identity 'iPhone Developer: MyName' appears more than once in the keychain. The codesign tool requires there only be one.
I check the keychain, and sure enough there are the two provisioning profiles for development, one from July and the one I used to submit to the iTunes Store in August.
Now what I want to do is get rid of the old one, and then connect my iPad up to the new one. I can get rid of the old one fine, but I cannot connect my iPad to the new one, it insists on using the old profile, even to the point of re-attaching it to the keychain after Ive deleted it.
Can anyone tell me:
How to connect my iPad to the new provisioning profile?
And while we are at it, can anyone shed any light on why this entire process is so convoluted and difficult? Considering that so much of Apples interface is so well designed and fluid, this process of registering certificates and applying them to different devices and Apps seems so backwards. I initially suspected this was just me, but googling for these error messages reveals that there are many who are struggling at various points along this process.
This has nothing to do with Xcode and everything to do with keychain.
Open keychain.
Find the signing certificates that are tied to your provisioning profiles.
Delete one. You probably want to keep the newer one, so look at the expiration dates and remove the one that expires first.
Restart Xcode
You may need to update your provisioning profile if it isn't tied to the new certificate, but it won't be as painful as creating a new certificate.
Here's a broad overview of how code signing in Xcode works. It a bit much but will explain what's wrong with your configuration, and how you can fix it.
There are three parts to the mechanism that ensures that you are who you say you are and that your app is allowed to run where it wants to.
You've got a pair of keys, one public and one private. Your public key matches your private key, which identifies you.
Your keys are used to generate certificates. Generally, you'll have one certificate for development and one for distribution,either on the App Store or via Ad Hoc distribution. These certificates permit you to provision your apps.
Each certificate is used to generate provisioning profiles. The profiles must be attached to either a development or a distribution certification. A distribution profile either works on the App Store, or it contains a list of device IDs which may run apps signed with that profile.
If your certificate is expired, the provisioning profiles that are created with it are going to be invalid. In this case, replace both the certificate and the profiles. Generate a certificate signing request (CSR) from Keychain Access and upload it to the developer portal.
If you have multiple certificates in your keychain, Xcode won't know which one to use. This may happen if you renew your certificate and don't remove the old one. (It may also happen if you exported your developer profile and then imported it later. Your old certificates will carry over.)
If your provisioning profile is expired or invalid, you can renew it in the developer portal without generating a new CSR. You can just attach it to an existing valid certificate.
Certificates can't be carried over from one machine to another without moving the original key pair that requested it. Exporting the certificate from Keychain will export the keys as well.
Delete the old one, and start build with new.
One more way you can try , set code signing identity with profile you want to run in both target as well as project build setting.
Hope it will help you.
Otherwise you have to delete old one.

What is best practice for iOS client enterprise distribution?

There is a lot of information about iOS distribution. I think I understand the different distriubution models, but I am looking for best practice for distributing an app to a client.
I have a client who has an Enterprise developer account and uses AirWatch for MDM. Here is how I am going to recommend to them that we distribute the app to their organization since they have no one technical on staff that has any experience with Xcode or iOS development and they will not be given access to the source code:
Add me as a member of their developer account
I build the app using their certificate
I give them the .ipa and plist file to distribute either through MDM or website.
Is this the correct way to do this? What if I am going to sell this same app to three clients - would I do it a different way? Is there anything else that needs to be done to distribute through AirWatch?
Again, looking for best practice and how others are handling this situation. Please clarify if I have anything wrong.
UPDATE: Thank you all for the answers. From what I have learned how this is done depends directly on how the client wants to handle the situation. In the end the client added me as an admin on their account (we have worked together quite a bit). I was able to create the distribution profile, build, and deploy the app to them. Not all clients will do this for security reasons. In that case, they will need to provide you will a cert as stated below, or you will need to build the app on one of their machines as Buckeye said below...or go through Apple to distribute the app to them.
Feel free to correct any of this info if it is incorrect. I really think this is helpful information for a lot devs.
I am accepting Patrick's answer because it is the closest to what I actually did.
There are two ways you can do this, but for both you must be added as a member of your client's developer team. Once you have done this, you (or more likely your client) will choose weather to use their in-house certificate or your own distribution certificate that you will manage.
It can be done either way, it is only a matter of who will have authority in the future to submit apps with the same certificate under the same account. That authority resides in the possession of the associated key pair of the certificate. If you are added to the client's dev team and download their distribution certificate, you will NOT have this key and cannot sign distribution builds with associated provisioning profiles.
Therefore, you must either get a .p12 export of the certificate (which contains the key) from the client to install on your machine so that you may sign with it. This will allow you to submit from your machine, but you are then in possession of your clien'ts private key, which they would like to protect. Your other option is to use your own Certificate Signing Request to create a Distribution Certificate on the client's developer account. In this situation, only you have control over the certificate and the client must create new ones if they wish to work with other developers in the future.
Once you have done that, here is an informative guide for enterprise distribution.
As an Enterprise Agent I will tell you that unless your client lives under a rock (technically speaking regarding the Apple dev portal) I doubt they're going to give up the private key and cert. If they have zero legal/contractual access to the source code you've created the only course of action, speaking from experience, would be for you to visit their facility with the source code, compile it on their box that houses the private key & enterprise distribution cert, build & deliver the IPA and finally take the source back with you. That is how I have compiled every build with a 3rd party vendor where we don't own the source and need to deploy internally.
On the flip side of this argument if the client is, for some wild reason, willing to give up the keys to their enterprise castle and export the private key & enterprise distribution cert for you to use... for YOUR sake I would get in writing what the scope of your usage is with that cert and somehow document the fact you have deleted the key & cert after the process is over. Don't open yourself up to liability because if they share it with you there's a chance they may also share it with someone else and as we all know, not all development entities play by the rules. You wouldn't want to get accused of creating some rogue app under their name.
Regarding re-signing the IPA file... AirWatch won't let you do it. AW interrogates the IPA when you upload it and it will note that the embedded provisioning profile doesn't match the re-signed IPA and tank. It becomes a chicken & egg situation where you need the provisioning profile on the device before you install the app however AirWatch won't let you deploy the app unless the aforementioned embedded profile is correct.
Also, #Caleb is correct regarding B2B but the pricing model goes from the project to per-seat (iOS device). In other words if your contract is "you can install this app on an unlimited number of devices" the B2B approach is going to blow up in everyone's faces.
EDIT:
Below are your options when editing a Development Provisioning Profile in an Enterprise iOS Account:
Obviously here you can pick & choose developers and their devices from within the portal that can compile to that profile.
Now here are your "options" for editing the Enterprise Provisioning Profile:
As you can see you don't get an option to edit which portal users or devices can use this profile because it's tied to the Agent's CSR/private key and is deployed globally.
You would need:
Their certificate.
Their provisioning profile.
It's a quite common practise to do this.
My question is, is this the correct way to do this?
Yes.
What if I am going to sell this same app to 3 clients, would I do it a different way?
No, you'll do the same thing. You'll need to build the app separately for each client using each client's distribution certificate.
Another option is to build the app and sell it to your clients using the B2B distribution mechanism.

Resources