Weird "The executable was signed with invalid entitlements" error... seems caused by iOS 8 sharing? - ios

Due to iOS 8 sharing, I've had to create a bundle ID and provisioning profile for sharing. This new bundle ID is linked to my existing bundle ID through an app group, and my entitlements file specifies the app group. Now, however, my wildcard provisioning profile doesn't work. When I try to build, Xcode says "The executable was signed with invalid entitlements". Only when I use the provisioning profile with a specific bundle ID does it work. It's becoming a huge issue for my company.
Any ideas? We want to use a wildcard because we add devices a lot, and a wildcard doesn't require a refresh of our provisioning profiles for all the devs.

When you need to use special entitlements (iCloud, push notifications, etc.) you can no longer use wildcard IDs. You will need to create a unique ID on Apple's dev site for each of your app that needs these capabilities, if each of the apps need to be installed at the same time on one device.
If your different apps will never need to be installed by the same person, you could get by having multiple apps use the same bundle ID, but I wouldn't recommend it. If someone has App A on the device, and at some point in the future needs to install app B, it will replace it, and could cause problems if the app uses things like Core Data.

Related

iOS/OSX App Group Ids, start them with "group." or "team-id."?

When creating a App Group id in the Provisioning Portal (or whatever its called now), it says to "Enter a unique identifier for your App Group, starting with the string 'group'" and seems to enforce that in the entry field. Also, lots of sample code uses app group id strings like "group.com.company.blah".
However, the definitive sections I've seen to linked throughout the documentation,
App Sandbox Design Guide > App Sandbox In Depth > Container Directories and File System Access > The Application Group Container Directory and Entitlements Key Rerefence > Enabling App Sandbox > Adding an App to an App Group, directly contradict this, clearly stating "must begin with your development team ID, followed by a period".
The examples given in those section are like "Z123456789.com.example.app-group" and "DG29478A379Q6483R9214.HolstFirstAppSuite" respectively. (whah, is that last one a super weird team id or what?)
So with this inconsistency, what do I do to get a App Group ID to work? Should I enter in the Provisioning Portal "group.TEAM-ID.com.example.blah"? And should I use this same string in my source code strings, or omit the "group." part to be like the many code examples? Or is the documentation wrong and the team id is never needed?
Context ... I've been trying to update an iOS cocoapod's test app so I can see extension <-> app communication in action. After updating the app ids and group id to one's in my control, and when using a group id similar to the project's original one, like "group.com.mycompany.thingie", I see containerURLForSecurityApplicationGroupIdentifier: do nothing but return nil and nothing else has fixed it.
UPDATE: (added this for clarity seeing how SO informs me that this Q is getting many hits) It turns out this stuff is more forgiving than I originally thought, as the nil result turns out to have been (mostly?) my doing. See the answer & its comment thread. I haven't checked to see if the documentation & examples are any clearer yet.
On https://developer.apple.com inside "Certificates, Identifiers & Profiles" when you go to the "App Groups" section and first generate your App Group, all that is required is the enforced group.com.companyname.appname
As long as com.companyname.appname matches what you have setup as the bundle identifier for your target underneath general, you should be able to then go to "Capabilities" tab, turn on "App Groups" click the refresh symbol and the group you just created in Provisioning Portal should appear there, as "group.com.companyname.appname" you'll have the option to check it off, and then will have an error with entitlements. Clicking "fix issue" should automatically resolve it.
Now if you navigate to you entitlements file you'll notice that "com.apple.security.applications-groups" will have an item and it will be set to the exact same "group.com.companyname.appname" value.
I've tested on devices and have no issues yet. This doesn't account for the inconsistency in documentation, but I can guarantee that this works.
I got bitten by the inconsistency in this between iOS and macOS while submitting the macOS Sierra version of my app.
group.better.fyi works for iOS submissions but results in the following error during macOS submissions (runs perfectly well otherwise, with no warnings or errors):
ERROR ITMS-90286: "Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on macOS. Specifically, value '[group.better.fyi]' for key 'com.apple.security.application-groups' in 'ind.ie.Better-Mac.pkg/Payload/Better.app/Contents/PlugIns/Blocker-Mac.appex/Contents/MacOS/Blocker-Mac' is not supported. This value should be a string or an array of strings, each starting with your TEAMID followed by a dot '.' ."
Replacing that with $(TeamIdentifierPrefix)better.fyi in the Capabilities tab under App Groups fixed the issue.
This does, of course, create an inconsistency between the iOS and Mac apps.
tl;dr version: https://stackoverflow.com/a/66647419/15809
But if you want to know all the details behind all this, please see below.
iOS
In the portal, all app group IDs created must start with group.; the portal will actually enforce that, so it's not even possible to register a group there without that prefix.
If the app group ID is then set on an app ID in the portal and an iOS provisioning profile is created for that app ID, the app group is embedded into the profile exactly as it has been registered. Take a look at such a profile and you will find the app group ID there.
If an iOS app has app group IDs in its codesign entitlement file, codesign will ensure that the group IDs from the entitlement are also found in the provisioning profile, otherwise it will refuse to sign the app. The provisioning profile thus whitelists the usage of these app groups.
When you configure an app group ID for an app in Xcode at the capabilities section, Xcode will put the ID into the codesign entitlements file for you. The app groups configured there for iOS apps must match exactly the app group IDs registered in the portal.
macOS
For macOS, though, things are entirely different!
If you add an app group ID to an app ID in the portal, this has no effect on macOS provisioning profiles created for that app ID. Have a look yourself; the app group ID is nowhere found in the generated profiles! Thus on macOS, a provisioning profile does not whitelist the usage of any app groups. You can put any app group ID into your entitlement files, this will always sign as codesign doesn't care. Codesign doesn't even care if your app group ID is prefixed by your team ID (or at least it didn't use to in the past, maybe it does as of today).
Unlike on iOS, the uniqueness of app group IDs on macOS is not enforced by the portal, it is enforced by the fact that Apple requires your app group IDs to start with your team ID, so uniqueness across teams is guaranteed and enforcing uniqueness within your own team is your own task.
Actually you don't need to register app group IDs for macOS apps at all in the portal. It's enough to just put your desired app group ID into your Xcode project capabilities and thus into your entitlement file. Many people think they have correctly registered their macOS app group when they register group.TEAM_ID.<whatever> in the portal and some magic makes this group work without group. prefix on the Mac, but that isn't the case. They just registered an iOS group of that name and the reason why TEAM.<whatever> works on the Mac is because that group doesn't require registration in the portal.
Now some readers will say: Wait a minute; if I can just put any app group ID into my entitlement files and it will always sign, who is actually enforcing that it is prefixed with my team ID? The Mac App Store. The Mac App Store won't allow you to publish an app with an app group ID that is not prefixed with the team ID of the publisher. If you try, the upload will fail.
App Groups and Security
You may wonder: Who is enforcing that app groups are prefixed by your team ID for apps distributed outside of the app store? Nobody. But then apps distributed outside of the app store can claim to be a member of any app group, even one from a different developer team, so how would that be secure? It isn't. Apps distributed outside of the app store don't even have to be sandboxed and if they are not sandboxed, they have access to your entire disk, including all app group folders of all apps, so how would that become any less secure by incorrectly claiming to be a member of an app group?
Apps distributed outside the app store may be sandboxed if they wish to restrict themselves for security reasons but even if they opt-in to that, they are free to poke as many holes into their own sandbox as they need or desire since unlike when distributing via the app store, there is no review that will ensure they only poke required and justified holes.
On iOS all apps are always sandboxed and distributed via the App Store, so this question doesn't even arise.
App Groups and Keychain Sharing
What about keychain item sharing? Keychain item sharing via app groups only works on iOS, not on macOS; for exactly that reason! It would be insecure on Mac. On macOS only sharing with keychain access groups works and those are in the provisioning profiles, also in macOS profiles, and for those codesign will always enforce that the profile whitelists them before it signs anything.
Reference from Apple
You'd like to have all of that confirmed directly by Apple? Sure, here is the reference provided by our most famous Apple tech support guru, Quinn:
https://developer.apple.com/forums/thread/133677?answerId=422887022#422887022

iOS8 extension needs own provisioning profile?

I am starting an iOS 8 extension but I can't run it on my device. The error when trying to run it is:
No matching provisioning profiles found
The provisioning profile specified in your build settings
(“ExtensionName”) has an AppID of net.company.AppName which does not
match your bundle identifier net.company.AppName.ExtensionName.
Xcode can resolve this issue by downloading a new provisioning profile
from the Member Center.
Do I need a separate provisioning profile for both the main app and the extension ?
Should they share a bundle identifier (by default it adds the extension name to the bundle identifier, so perhaps not) ?
If it has a separate bundle identifier how is that reflected in the provisioning profile (if there is a separate one) ?
It would seem that Xcode would prefer it that way, however there's nothing stopping you from using a wildcard profile until you want to do an Adhoc or Release to the App Store. More to the point of your question though, for every target that you have, you need a profile and bundle ID. So yes, you "need" another provisioning profile for your Extension, although I expect Apple to streamline this process.
All in all, it's probably best to just use a WildCard dev profile until you need a provisioning profile. Remember this is all a beta, and they're still working on pretty much everything.
Extensions are separate targets from the host app. You have to treat them as though they are separate apps with different bundle identifiers and different provisioning profiles.
It's best if you just create them during testing instead of using wildcards because you may need to test some capabilities that you enabled, for example App Group so that your extension and host app can access the same container.
Note that if you want to have any capabilities enabled for your host app and extensions, you have to enable them individually for all of them.
I've located this documentation pertaining to App Extensions. If you read the bottom of page 20 if seems that using the same distribution certificate is actually suggested. I've gone ahead and changed my bundle identifier for the Today Extension to extend my applications. For example, com.DeveloperName.AppName.TodayExtension, created an App ID in the Dev Center to correspond with that, and created a distribution profile for it.
My app +Quotes has successfully been updated by following these steps. I have not experienced any issues with the app or extension, but Xcode does seem to get a little confused when trying to auto assign the correct provisioning profiles for my extension now. Selecting them manually solves this.
You do need a separate provisioning profile for you extension but with the same certificate your main app has. When you are creating a new provisioning profile, your Extension's app id will also appear in the list, choose that, and proceed to create a new provisioning profile.
Also choose that provisioning profile in the target of your extension.
I simply use "Automatically manage sign in" until I need to push to App store. This works out of the box with simulators, haven't tried with devices yet.
Few pointers for Appstore Build:
I created one wildcard id for every notification extension, but the prefix of this wildcard bundle id should match your app's bundle id as prefixed. If it's not like this, this error will come up: "Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier". So, if your app's bundle-id is: "com.companyName.appName", the wildcard bundle-id for your extension should be "com.companyName.appName.*". You can then replace * with a specific notification extension in the XCode. Note apple only allows one period(".") after the app's bundle id for naming your extension's bundle id.
The version and build number of your extension should match that of your app.
Once App Id is created, create a distribution provisioning profile with this and use it in XCode.

Do i need a separate Distribution for each Apple AppStore submission?

I'm so confused -
after an entire day's struggle, i finally figured out how to submit my app to Apple via archiving & distributing from xcode.
... that was my free version
now i made my code changes, and on my pList file, i changed the Bundle Identifier to com.blah.mygame.pro instead of com.blah.mygame.lite
i also changed the Bundle name to be My Game Pro instead of My Game Lite
but now i'm confused - when i click on the project in Xcode, and i hit "Target" instead of "Project", i can't find my release/distribution profile! (my develop/debug profile) is still there.
if i were to click Project instead of Targets then i actually do see my previous distribution profile.
however, in my develloper portal, i had actually set my distribution profile to be linked up with the "com.blah.mygame.lite" identifier. was i not supposed to do this???
weirdly enough, when i made my distrubution profile earlier today, i say something like "mygame * -" or something that i coulda linked it to. but i just chose com.blah.mygame.lite without thinking
are you supposed to have multiple distribution profiles? one for every app? what i just want a lite and pro version?
** edit:
bonus points for this:
if i only needed 1 provisioning profile, (and since i messed up naming my previous provisioning profiles)... how do i rename all my distribution profiles without it interfering/messing up with my apps?? it's already submitted and awaiting approval
* EDIT # 2:
okay, i got both apps submitted with 2 separate distribution profiles.
however, is there any way that i can rename a distribution profiles while the app being submitted is still using it??
i had mistakenly named it "My Company Distribution Profile" when i should have named it "Distribution Profile for My Game Pro Version"
You have two options for fixing it:
Use a AppId like. com.blah.mygame.* . You can replace the * with any number of strings and use it for creating different application.
I won't recommend this approach, because the issue with this is you won’t be able to use push services or in-app purchases. You might not plan to use these services now, but if you change your mind, you won’t be able to change your app ID without creating a new app.
Create different AppId for different Apps. It'll be a good approach
Sounds like you're using a single AppID for both of your apps. You can only use one provisioning profile for multiple apps only if the AppID bound to that profile has a wildcard (e.g. "com.sample.*").
quoted from the iOS Provisioning Portal:
The Bundle Identifier portion of an App ID can be substituted with a
wild-card character (asterisk '*') so that a single App ID may be used
to build and install multiple applications. If the wild-card character
is not used, the Bundle Identifier portion of your App ID must be
input as your CF Bundle ID in Xcode to allow the application to
install on your device. The Bundle Seed ID portion of your App ID does
not need to be input into Xcode. Wild-card App IDs cannot be used with
the Push Notifications or for In-App Purchase.
I hope you have created an AppId with this bundle identifier com.blah.mygame.lite and created a distribution profile linked with this AppId. By doing like that, you can run or archive your apps only if it is having the same AppId like this com.blah.mygame.lite. If you want to create an AppId to run all apps, then you need a Wildcard AppId like this com.* . And If you think you need to run the app with AppId com.blah.mygame.pro then you need to create another appId like that and associate that appId with another distribution profile or modify the old one and download and install it and use.
There is no need of distribution profile for every app....one is enough for every time but
your bundle identifier is same as you given in your distribution provisioning profile when
you create it first time....

Submitting app with iCloud enabled: is it possible? Apple: Invalid Code Signing Entitlements

Two apps, say, AppX and AppXLite, use the same iCloud key-value storage with the same Store Identifier and in entitlements file I see $(TeamIdentifierPrefix)com.company.AppX
Everything works in adhoc and debug builds. But when I try to upload AppXLite to appstore, I get an error:
Invalid Code Signing Entitlements - The signature for your app bundle
contains entitlement values that are not supported. For the
com.apple.developer.ubiquity-container-identifiers entitlement, the
first value in the array must consist of the prefix provided by Apple
in the provisioning profile followed by a bundle identifier suffix.
The bundle identifier must match the bundle identifier for one of your
apps or another app that you are permitted to use as the iCloud
container identifier. Specifically, value "YYXXXXXXYY.com.company.AppX"
for key "com.apple.developer.ubiquity-container-identifiers" in
AppXLite is not supported.
Agree with this letter, but then everything is ok: prefix, provided by Apple, bundle identifier. If not, this won't work in adhoc build. But why do they say that things aren't right?
Yes, I know that there are tons of answers here, I read them. People say that one should disable iCloud support in app in provisioning portal to fix such issue. If I do this my apps will no longer see iCloud, but this is one of key features!
I have an idea that I should upload AppX first, before AppXLite, as both apps use AppX's bundle id as Store Identifier. But I've added both apps on provisioning portal, so appstore should know "the bundle identifier for one of my apps" as Apple stated in the letter.
Do anyone have experience of uploading iCloud-enabled apps to Appstore?
If you faced the same:
Kill all profiles in provisioning portal
Kill all profiles in Xcode and devices
Recreate all needed profiles (I've created dev, adhoc and appstore for each)
Download them manually and drag to Xcode.
Clean and rebuild all apps
Submit first app, which bundle id is shared between them as a Store Identifier of iCloud.
Submit all the rest apps.
Result: everything in "Waiting for review" state.

Submitting an App to the App Store that uses iCloud, invalid entitlements

I have an app I tried to submit to the app store. Like many others I'm getting the following e-mail from the app store approval process. The answer to the other questions seems to be, uncheck iCloud from the App ID, but my app uses iCloud and I wouldn't want to lose that functionality. Has this been solved yet?
I did double check that my App ID's Bundle Identifier matches the value of the items that are entered in the Entitlements area of the Target Project. Thanks for your help!
Dear Developer,
We have discovered one or more issues with your recent binary
submission for "XXXXXX". Before your app can be reviewed, the
following issues must be corrected:
Invalid Code Signing Entitlements - The signature for your app bundle
contains entitlement values that are not supported. For the
com.apple.developer.ubiquity-container-identifiers entitlement, the
first value in the array must consist of the prefix provided by Apple
in the provisioning profile followed by a bundle identifier suffix.
The bundle identifier must match the bundle identifier for one of your
apps or another app that you are permitted to use as the iCloud
container identifier.
Specifically, value "XXXXXXX.com.xxxx.xxxxxx" for key
"com.apple.developer.ubiquity-container-identifiers" in WeHeartApps is
not supported.
Once these issues have been corrected, go to the Version Details page
and click Ready to Upload Binary. Continue through the submission
process until the app status is Waiting for Upload and then use
Application Loader to upload the corrected binary.
Regards,
The iTunes Store Team
Found the answer, it seems as though my Provisioning and Distribution Profiles were out of sync. When in doubt;
delete your provisioning and distribution profiles on the iOS provisioning portal
recreate them on the iOS provisioning portal
Delete the old ones locally.
Download the new ones from the portal.
Clean the project
Drag the new profiles onto the xcode app
Do a fresh "Build for Archiving." ( Make sure iOS device is selected for this to be enabled )
Finally archive
Go to the organizer and Validate the Archive
Submit to the app store!
Cheers
For others who have apps sharing data between both Mac and iOS devices via iCloud, you will also run into this problem if you try to submit the platform which depends on the other's bundle identifier first. This is because the bundle identifier you're trying to share data with has not yet been registered as an app.
The solution is simply to submit the app whose bundle identifier you're using as the com.apple.developer.ubiquity-container-identifiers entitlement first.
For example, if you're sharing data between a Mac app with a bundle identifier of com.mycompany.osx, and an iOS app with a bundle identifier of com.mycompany.ios, you will likely choose one as the mutual data store. If you choose the iOS version, the your Mac app will have the value "com.mycompany.ios" set as your ubiquity storage and iCloud key-value storage. In this case you just need to submit the iOS app first so that the "com.mycompany.ios" bundle identifier registers as a valid app on Apple's side.

Resources