How do I produce an iOS Release Build that my client can sign on their end?

Solution 1:

Most of these answers seem complicated and out dated. I think the simple answer is to make an archive with a Developer profile.

This is a solution which I am currently investigating for my own purposes (not fully tested):

You just need developer access (not team agent) to their account and create a Development provisioning profile that authorizes you to build the specified App ID (you need to specify the App ID, because it gets compiled in). Then Archive the app with the Development profile, and share the archive with your client. They can then re-sign the archive with their own Distribution profile.

One complication is that when you build an archive with a developer profile, the entitlement attribute get-task-allow gets set to true, but needs to be set to false for distribution, so you have to work around that by setting it manually your Entitlements.plist - see my question here: Can I archive with a Developer certificate, then re-sign it during submission with a Distribution certificate?

Solution 2:

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.

  1. Client invites developer to their team in the Member Center as an Admin
  2. Developer accepts the invite (should be in your email)
  3. Developer opens Xcode's Organizer -> Devices Tab -> Provisioning Profiles and hits Refresh in the lower-right corner. Make sure you choose the right team and you should get a few new items.
  4. In Xcode, leave Code Signing Identity settings to their default values (or reset them to iPhone Developer for Any iOS SDK)
  5. Archive the app
  6. In Organizer, right-click the archive and select Show in Finder
  7. Send the .xcarchive file to your client
  8. Client must have Xcode installed
  9. Client double-clicks the .xcarchive file which should open it in Organizer
  10. Client clicks Distribute and signs the app with their identity
  11. Profit

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.

Solution 3:

I had the same problem. This was how I finally solved it:

  1. Client created a development certificate.
  2. Client created a development provisioning file using the same App ID as the distribution provisioning file.
  3. Client exported development certificate (.p12).
  4. Client sent me the .p12 file and the development mobile provisioning file.
  5. I imported the clients p12 file into my keychain
  6. I imported the client's provisioning file into Xcode.
  7. Set the code signing Identity for my build configuration to use the client's provisioning file.
  8. I Archived the app.
  9. I Sent the Archive to the client.
  10. The client created their distribution build by signing the app with their distribution provisioning file. (They were distributing the app internally for testing.)

The client was not so concerned with sharing a development certificate as they would be sharing their distribution certificate.

I also had to create entitlements.plist with "Can be debugged" (get-task-allow) set to NO, and reference it in the build configuration (under Code Signing, Code Signing Entitlements).

Solution 4:

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.

#!/bin/sh

DestFile="Signed_$1"
SigningCertName="YOUR DISTROBUTION CERT NAME HERE FROM KEYCHAIN"
AppInternalName="APP NAME FROM INSIDE PAYLOAD FOLDER.app"

echo
echo "Going to take the app $1 and resign it as $DestFile"
echo

if [ "$2" = "iphone" ] ; then
        echo "Using iPhone Profile"
        echo
        BundleID="com.YOURCOMPANY"
        ProvProfile="/Users/YOURNAME/Library/MobileDevice/Provisioning Profiles/PROVISIONINGPROFILE.mobileprovision"
elif [ "$2" = "ipad" ] ; then
        echo "Using iPad Profile"
        echo
        BundleID="com.YOURCOMPANY.ipad"
        ProvProfile="/Users/YOURNAME/Library/MobileDevice/Provisioning Profiles/PROVISIONINGPROFILE_iPad.mobileprovision"
else
        echo "You must enter either iphone or ipad as the second parameter to choose the profile to sign with."
        echo
        exit 1
fi

rm -f Resigned.ipa
unzip -q $1 -d temparea
cd temparea/Payload
echo "*** Original Signing ***"
echo "************************"
codesign -d -vv $AppInternalName/
cp "$ProvProfile" ./$AppInternalName/embedded.mobileprovision
export EMBEDDED_PROFILE_NAME=embedded.mobileprovision
export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate

#Update the Info.plist with the new Bundle ID
sed 's/>ORIGINAL BUNDLEID HERE</>'$BundleID'</' ./$AppInternalName/Info.plist >./$AppInternalName/Info.plist.new
mv -f ./$AppInternalName/Info.plist.new ./$AppInternalName/Info.plist

# this will do a rename of the app if needed
# sed 's/>ORIGINAL APP NAME</>NEW APP NAME</' ./$AppInternalName/Info.plist >./$AppInternalName/Info.plist.new
# mv -f ./$AppInternalName/Info.plist.new ./$AppInternalName/Info.plist

# echo "Hit enter to proceed with signing."
# read TMP
codesign -f -vv -s "$SigningCertName" -i $BundleID $AppInternalName

echo
echo "*** New Signing ***"
echo "*******************"
codesign -d -vv $AppInternalName/
cd ..
zip -r -q ../Resigned.zip .
cd ..
rm -R temparea
mv Resigned.zip $DestFile
echo
echo "New IPA Created, $DestFile"

Solution 5:

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