My scenario
I wrote an iOS app for a client. The project is almost over and now it's time for them to put it in the App Store. I've been sending them development builds throughout the development process. Those builds had a bundle id based on my company and my client's project like so: com.mycompany.clientname.projectname
. I signed those Ad Hoc builds with an Ad Hoc Distribution Provisioning Profile that I created in my own Provisioning Portal account.
Now that it's time to go to the App Store, I need to do a Release Build and send that for them to sign with their own App Store Distribution Provisioning Profile. This also implies setting a new Bundle ID for the project.
My problem
I need to get a compiled app to the client for them to sign with their provisioning profile. However, I need to set the Bundle ID to what they're going to use first. Let's say it's com.bestclientever.appname
. Xcode 4 won't let me archive the project now because doing so requires code signing. I can not code sign it because I can not create a provisioning profile with the same Bundle ID as what they have set up in their Provisioning Portal (the Provisioning Portal enforces uniqueness—as it should).
Have I made any incorrect assumptions or misunderstandings here? ie. Do I really have to set the Bundle ID to what they're going to sign with?
The Question
Is there any way to archive, or otherwise build, an iOS app without code signing it? Like a "sign later" setting or something?
Or, is there a way to build the app with one bundle id but then someone else be able to sign it with a provisioning profile for another bundle id (either by changing the bundle id of the compiled app or some other signing method)?
How can I build the final release build but have someone else sign the app for distribution to the App Store?
What I've tried or explored
- Acting for the client.
- With other, less savvy clients, I've ended up just getting their Provisioning Portal and iTunesConnect credentials and just doing the final build as them. That won't fly with this client. It's a big company with strict security guidelines and a lot of red tape.
- Spoofing as the client.
- This is similar to the one above and won't work for the same reasons. It sounds really fishy to ask my client "can you export your private keys and send them to me"? This technique is described in this answer: How can I send iOS app to client, for them to code-sign
- Sending the client my project source code and letting them do the release build.
- A license to the source code was not in our agreement. Additionally, this client does not want to get involved with source code (hence outsourcing it). I would entertain this as a last-resort option, but there's gotta be a better way!
- Getting set up as an Admin-level developer in their Developer Member Center.
- Unfortunately, only the Agent-level user can create a Provisioning Profile (as far as I can tell). It seems like there ought to be a way to either let me create a profile that I can use to sign the build or generate a profile for me. I can't find either option.
I just confirmed at WWDC 2012 that the following technique works. It best satisfies my constraints of little client involvement, low client expertise, a simple signing process, and source code ownership.
This does require the client to use the Member Center on developer.apple.com and to use Xcode a little bit (but just the Organizer!). If your client has technical capability problems at this level then I recommend just taking over and doing it for them (and charging for it!). Ask for their developer login and password and just act on their behalf as if you were an employee.
Ed note: Trading keys around is a terrible compromise because it's more technical and involved for the client and more hacky and risky for the developer. It should be considered a non-option given these two better options.
Best alternative way would be to ask the client to export his distribution certificate private key into .p12 file and send it across to you alongwith the distribution profile with which you can generate a App Store distribution build for your client.
Best of luck!!
Regards, Sam
Ok, found a way to do it without sharing provisioning profiles or certificates.
The idea is to insert a "run script" build phase to trick XCode into signing an App it didn't compile, so you can send a compiled (unsigned) App to the client, and then their XCode signs that App with their cert and profile.
How to do it:
Step 1: Make XCode generate an unsigned Release .app (I'll call this "App A"). See "To Disable Code Signing" here: https://stackoverflow.com/a/10171462/375486
Step 2: Create a new XCode iOS project and remove from it all build phases you can, so it creates an empty .app file (I'll call this "App B")
Step 3: Add a "run script" build phase to Project B which copies the contents of "App A" into "App B". In my case I used this:
Step 4: Send the "B" XCode project to the client, with all the necessary files.
Step 5: The client builds the B project. Under the hood, XCode will run the "run script" command, then sign the resulting app, and the client gets a perfectly signed App.
And that's it :)
Huh, all these look way more complicated then they have to. I use this this:
I just got off the phone with Apple. They say this is the only way to do it: https://developer.apple.com/library/ios/#qa/qa1763/_index.html
The client adds you to their team, and gives you specific privileges.
I believe I have found a way to do exactly what you want, I haven't done extensive testing or tried to upload to the app store but from the testing I have done it seems to be good. The resign and the addition of my provisioning profile is working as I can install it on my devices defined in the AdHoc profile with no manual profile installation needed. Second test was I got an iPad and an iPhone version of an app with the same bundle ID from xCode, at first I could not have both in iTunes but after the resign and bundle ID change I was able to have both installed. I also tried changing the app name and that worked as well, it showed on the device and in iTunes with the new name. Below is my script, it's designed to resign a specific app for me, so the profile and bundleID are hardcoded. I flip between an iPhone and iPad version of the app so I added that as a parameter to the script. But you should be able to take the principles I have here and refine them for yourself.
The guts of this builds upon articles like Further adventures in resigning for iOS from Dan's Dev Diary and very similar to Erica Sadun's App Signer listed above. The main addition I made was the editing of the Info.plist prior to resigning.