Search code examples
iospush-notificationapple-push-notificationsprovisioning-profileenterprise

Push notifications not working after switching to Enterprise distribution


I had push notifications working on an app that was using an ad hoc distribution. My client then bought an Enterprise license, and I generated new certificates/profiles, archived the app, and now we are distributing via Enterprise, but push notifications are no longer working. What steps would I have to take in order to get them working on the Enterprise version? Thanks!


Solution

  • Based on your description it sounds as though you did your original implementation on an AppId registered under one developer account, and then attempted to migrated the build to a second developer account.

    In APNS parlance, the server that generates the push notification payload objects is called the provider and must register an APNS certificate keypair to be able to establish a secure connection between your server and the relevant Apple Push Notification gateway (Sandbox or Production). This keypair is exclusive to the AppId for which it was registered, and AppIds are exclusive to the Developer Account under which it was registered -- even with a precise matching AppId certificates registered under one account can not be transferred to a second account. If that were possible, I could look at your app's AppId, register that AppId in my own account and start sending spammy pushes to your app. Thankfully, the Bundle Seed ID is a silent element to all AppIDs and prevent that situation from occurring!

    I've answered a similar question about APNS Provisioning that might help further clarify what is going on behind the scenes, so you might give Why I can't add APNs Development iOS typed certificate to provisioning profile a read.

    If you want to see that your AppIDs are actually different you can use a couple of Terminal commands to export information from the original Provisioning Profile (where things were working) and from the Enterprise Provisioning Profile (where things aren't working) to see the differences:

    Copy and pasting the following, taking care to update the path to your specific .mobileprovision:

    /usr/libexec/PlistBuddy -c 'Print :Entitlements' /dev/stdin <<< $(security cms -D -i /path/to/your/original.mobileprovision)

    Then run this command a second time updating the path to your Enterprise provisioning profile.

    The output of this command will be a dictionary of key value pairs:

    Dict {
      get-task-allow = true
      aps-environment = development
      com.apple.developer.team-identifier = ABC1DEF2G3
      application-identifier = XYZW1ABC2D.com.mycompany.niftyapp
      keychain-access-groups = Array {
          XYZW1ABC2D.*
      }
    }
    

    You'll notice that the output of these two commands is different -- the application-identifier section and keychain-access-groups section will have different bundle seed IDs.

    So how do I fix it?

    The fix is quite simple and requires no additional development work in-app! You will, however, likely need to recompile with a new provisioning profile:

    • Because you've set things up already you just need to login to the Enterprise Account and enable Push Notifications in your Enterprise account's AppId
    • While in that AppID's configuration, you will need to generate a new SSL keypair and submit it to Apple just as you did for the original account.
    • Install the new certificate and private key on your Push Server
    • Edit your Enterprise Distribution provisioning profile, and install it in Xcode taking care to remove the old Enterprise Distribution provisioning profile.
    • Rebuild your application using the new Provisioning Profile.

    The rebuild may be necessary because if the Enterprise AppID didn't have Push Notifications enabled, the Enterprise Distribution Provisioning Profile's Entitlements block would not contain the aps-environment key and thus be prohibited from connecting with the APNS Gateways.