Code Signing Updates in Xcode 9

Written by: on September 7, 2017

In my last article regarding Xcode 8, I wrote about the latest additions in code signing. Whereas last year Xcode’s headlining feature was automatic signing, this year Apple is giving us more granular, manual control when exporting IPAs from the command line with Xcode 9.

In that article, I stated:

“Application distribution is a two-step process: compilation and code signing. Your app should first be compiled into an XCArchive and then exported to an IPA for distribution. Because of this, you do not need to have the exact release certificates and profiles set in your Release configuration. As long as the app compiles with the correct release flags, optimizations, etc., it can be signed with an AdHoc or even a Development profile. You just need to use the correct App Store or Enterprise profile when you export the IPA or submit to the App Store. This can help developers who don’t have access to the release credentials and certificates from seeing unnecessary errors that they cannot do anything about.”

Xcode 9 brings us a few updates to the xcodebuild command line tool that make this two-step process from Xcode 8 much easier. You can find all the available options by running xcodebuild –help. The specific options for -exportOptionsPlist will be at the very bottom. The relevant options I will be discussing are the following:

Available keys for -exportOptionsPlist:
...
    method : String

        Describes how Xcode should export the archive. Available options: app-store, package, ad-hoc, enterprise, development, developer-id, and mac-application. The list of options varies based on the type of archive. Defaults to development.

    provisioningProfiles : Dictionary

        For manual signing only. Specify the provisioning profile to use for each executable in your app. Keys in this dictionary are the bundle identifiers of executables; values are the provisioning profile name or UUID to use.

    signingCertificate : String

        For manual signing only. Provide a certificate name, SHA-1 hash, or automatic selector to use for signing. Automatic selectors allow Xcode to pick the newest installed certificate of a particular type. The available automatic selectors are "Mac App Distribution,” "iOS Distribution,” "iOS Developer,” "Developer ID Application,” and "Mac Developer.” Defaults to an automatic certificate selector matching the current distribution method.

    signingStyle : String

        The signing style to use when re-signing the app for distribution. Options are manual or automatic. Apps that were automatically signed when archived can be signed manually or automatically during distribution, and default to automatic. Apps that were manually signed when archived must be manually signed during distribution, so the value of signingStyle is ignored.

    teamID : String

        The Developer Portal team to use for this export. Defaults to the team used to build the archive.

The method and teamID are existing options: it’s the signingStyle,signingCertificate, and provisioningProfiles that are new in Xcode 9. The exportOptions.plist file you had used previously will be more verbose but the new options gives you much more control over the code signing of your IPA.

First, you need to include the new signingStyle key. Since I am mainly interested in manual signing, the value I will use is manual.

<key>signingStyle</key>
<string>manual</string>

Next, define the desired certificate with signingCertificate. This value needs to be the signing certificate that matches the provisioning profiles to be used. Values like iOS Distribution will try to automatically select the matching certificate. I prefer to select the exact certificate name with a value of iOS Distribution: POSSIBLE Mobile.

<key>signingCertificate</key>
<string>iOS Distribution: POSSIBLE Mobile</string>

Lastly, provide a dictionary of every bundleID in the app to be signed. This will be every app and extension that you are distributing. The key is the bundleID and the value is the provisioning profile to be used.

<dict>
        <key>com.client.appname</key>
        <string>Client App Release</string>
        <key>com.client.appname.watchkitapp</key>
        <string>Client App WatchApp Release</string>
        <key>com.client.appname.watchkitapp.watchkitextension</key>
        <string>Client App WatchKitExtension Release</string>

<key>com.client.appname.RemoteNotificationServiceExtension</key>
        <string>Client App PushExtension Release</string>
        <key>com.client.appname.Stickers</key>
        <string>Client App Stickers Release</string>
    </dict>

Here is an example of a complete exportOptions.plist:

I like to save multiple versions of the exportOptions.plist file alongside the app for easy creation of distribution IPAs. For example:

exportOptions-enterprise.plist
exportOptions-adhoc.plist
exportOptions-appstore.plist

This way, after an xcarchive is created, I can easily create multiple IPAs.

xcodebuild -exportArchive -archivePath MyApp-Release.xcarchive -exportOptionsPlist exportOptions-enterprise.plist -exportPath .

Every year, Apple continues to improve Code Signing and App Distribution. The latest additions to the xcodebuild command line tool in Xcode 9 really help developers reliably produce IPAs for distribution.

Jay Graves

Jay Graves

Jay is the Chief Technology Officer for POSSIBLE Mobile, a leading mobile development company. Jay’s expertise developing apps for some of the world's top brands has made him a respected leader in the space, with his work being featured on television, in iTunes and on devices inside Apple retail stores.
Article


Add your voice to the discussion: