Code signing issues and crashes after attempting to set up Keychain sharing - macos

I'm working on an app for Mac OS that consists of three binaries:
The main app, to be installed in the Applications folder.
A widget (for OS X Yosemite)
A LoginItem that monitors some stuff in the background (daemon-like, always running)
All three binaries connect to a certain web service with the same OAuth token. The token is retrieved by the main app (on first run, after the user signed in to the service) and stored in the system's Keychain.
To make sure the other two parts of the app can also access the same token, I'm trying to set up Keychain sharing. In Apple's Developer Portal, I've created three App Store Provisioning profiles, one for each binary. All of them are signed with the same developer certificate ("3rd Party Mac Developer Application").
In this situation, none of the binaries will run on my development system, citing "Code Signature Invalid". Also, in the system console, taskgated writes this message: "killed [app] because its use of the keychain-access-groups entitlement is not allowed (error code -67050)".
It is worth nothing that in the capabilities page of each target in Xcode, the Keychain sharing capability was enabled without any error whatsoever.
How do I solve this issue? The only thing I've came up with is simply disabling Keychain sharing, but this will require the user to click (Always) Allow when running the widget for the first time.
Another solution would be to eliminate the keychain altogether, but storing a OAuth token in an unsafe place like NSUserDefaults is not the way to go. I can't find a secure alternative for the keychain, which I think would be the best solution if it works anyway.

Related

Step-by-step recipe for signing Mac installers (.dmg)

Apple wants apps to be signed. With newer MacOS versions, unsigned apps look less and less welcome.
As a cross-platform developer with almost no knowledge of Apple specifics, I have to learn how to sign Apple apps. A step-by-step recipe would be helpful.
So far I understood all the following is necessary:
Register for an Apple ID [1].
Agree with endless pages of legalese.
Apply for an Apple developer account [2].
Choose among several categories (individual, nonprofit, government, ...).
Accept further pages of legalese.
Agree with unspecified membership fees that are waived for open-source projects.
Wait for unspecified time until you will or will not be admitted by Apple.
Create a certificate from Xcode.
Open or create an arbitrary project to get to the main menu.
In the main menu (Xcode) > Preferences > Accounts > Manage Certificates > "+" (bottom left) to create certificate.
In the main menu (Xcode) > Preferences > Accounts > Download Manual Profiles. Seems to create a file with extension .developerprofile.
From here, an unknown number of steps is missing....
Maybe the last step involves the command codesign [3],
codesign -s <identity> --keychain <full-path-to-keychain> <path-to-disk-image>
What is <identity>?
What is the keychain file?
Who can confirm or correct the above, and supply the missing steps?
Note that the build process shall ultimately be run from CMake. Therefore command-line tools are preferred over GUI actions.
[1] https://appleid.apple.com/account
[2] https://developer.apple.com/
[3] https://stackoverflow.com/a/37923530/1017348
You can build and sign to completion using Xcode, or you can build and then sign and notarise the binaries using codesign, altool, and stapler tools.
Xcode attempts to handle the complexity for you, at the cost of your not needing to understand or know about the individual steps involved. .developerprofile files are part of Xcode and Xcode is not essential to preparing a binary for distribution.
See Apple's Xcode Guide - Distribute your app and Distribute outside the Mac App Store (macOS).
Apple have also published the following guides on code signing and notarizing:
Code Signing Guide
Notarizing macOS Software Before Distribution
Identity
What is <identity>?
identity is common name field of the digital certificate being used to sign the binary. The digital certificate is an X.509 certificate issued by Apple. You can obtain certificates for submission to the Apple app stores, and distribution outside of their stores, through the Apple developer web site.
See Apple Developer - Certificates
Apple Developer Program membership is required to request, download, and use signing certificates issued by Apple. For developers part of a team enrolled as an organization, you must also be the account holder or an admin to request distribution certificates used for submitting apps to the App Store.
Keychain
What is the keychain file?
Keychain files are managed through the Keychain Access application on macOS, see Applications/Utilities/Keychain Access. By default, the user's keychain files are stored in ~/Library/Keychains.
The keychain file is where macOS stores secure user information, such as credentials and certificate keys. The keychain file needs to be specified for the codesign tool to locate the private key associated with the signing certificate.
See Apple Developer - Keychain Services:
Securely store small chunks of data on behalf of the user.
Computer users often have small secrets that they need to store securely. For example, most people manage numerous online accounts. Remembering a complex, unique password for each is impossible, but writing them down is both insecure and tedious. Users typically respond to this situation by recycling simple passwords across many accounts, which is also insecure.
The keychain services API helps you solve this problem by giving your app a mechanism to store small bits of user data in an encrypted database called a keychain. When you securely remember the password for them, you free the user to choose a complicated one.
Support from Apple
If the documentation linked above does not help, please contact Apple. The process you are facing is demanded by Apple, and Apple should burden the support it creates.
As a registered Apple Developer, you have access to Technical Support Incidents:
Requesting Technical Support
A Technical Support Incident (TSI) is a request for code-level support for Apple frameworks, APIs, and tools, and is available to members of the Apple Developer Program and Apple Developer Enterprise Program.

Avoid having to re-type password to access keychain item from macOS command line app after every re-compilation?

I'm building a macOS command line app that stores tokens in Keychain as kSecClassGenericPassword. I'm using a self-signed certificate to codesign the app for local development. (I am not adding any entitlements.)
The problem is what whenever I re-compile (and re-sign) the binary, I get a prompt for my admin password whenever the binary accesses the keychain item. According to this answer, keychain should detect that both versions of the binary are signed and have the same identifier, and not ask for my password. Is there anything I'm missing or any workaround to avoid having to enter my password so frequently?
I don't know for sure, but I strongly suspect the issue is that your certificate is self-signed. Most security decisions in macOS are based on the team identifier embedded in the signing certificate. This prevents a malicious program from stealing credentials from another application simply by giving itself the same bundle identifier and being signed. For the authorisation check to be skipped, both the bundle identifier and the team identifier must match.
I suspect that even if you did somehow embed a team ID in your certificate, because the certificate is not in turn signed/issued by Apple, the team ID would (rightly) not be considered reliable by the OS, so your binary is treated as effectively unsigned. I suspect the CDHash (cryptographic hash of the binary code) is used for authorisation instead, and your certificate is ignored.
I don't know your reasons for using a self-signed certificate, but as far as I'm aware you can get a very basic Apple Developer certificate from Apple for free, and using this to sign your binary should suffice for solving the issue you are encountering, as the free certificate includes a Team ID.
The only other workaround I can think of is to use a helper process with the sole purpose of storing and retrieving the credentials, and using XPC to communicate with this from your main binary. The helper process would hopefully not need to be updated as frequently as the main program, so you'd rarely see the authorisation prompt. This is of course still rather awkward, and now you need to secure the XPC service against malicious clients yourself.

How to avoid "unidentified developer" error by gatekeeper

As a developer of an app it could be quite a turn off if half of your users cannot open your app because they get following error.
[i know there is a workaround by going to sys preferences->security-> allow apps from "anywhere" but users of our apps are kids, they may not be in the best position to know how to do that]
What things I need to take care of in oder to avoid this warning, or to get apple developer identity?
This app has been published on App Store, so all the provisioning profiles and certificates are there. Now we want to put the app on our website, but before doing that we want to eliminate this gatekeeper hurdle.
In the screenshot above you can see that the right developer is selected while archiving.
The signing identity used for App Store submissions and for independent publishing are different. The latter requires a Developer ID identity be used. See Distributing Applications Outside the Mac App Store for more information about the process.

Can't validate and submit an App to the Mac App Store

I've done codesigning and submitting for iOS apps countless times. This time it struck me with the Mac App Store. I'm repeatedly getting the same error message:
"My Name" is a valid identity. However,
you do not have the associated package identity.
I've recognized this 2 topics here on stack overflow:
mas-code-signing-identity-private-key and mac-app-package-identity-not-installed
Nothing inside there solved the problem for me.
Thats how I (most reliably) reproduce this message:
I clean up all my certificates and private keys starting with "Mac Developer" or "3rd Party Mac Developer". Of course also the expired ones.
Revoking all the stuff inside the Mac certification portal.
Create App-ID (did it only once)
Create new certificate for Mac Development. I can only assume that this is comparable to the debugging certificates for iOS development.
Create new certificate for Mac App. Once again I can only assume that this could be something similar to a distribution certificate in iOS-development.
For completion reasons create a new certificate/profile for my system.
Create a production provisioning profile. I can only assume that this might be equivalent to an iOS distribution profile.
I then download all the certificate mess and install it properly. Some go into the Keychain, others got into the Preferences and XCode.
For making sure I restart XCode or even the whole Mac (doesn't change the frustrating outcome anyway).
I go to the project build settings and select the production provisioning profile, because I assume "production" is equivalent to "distribution". Changing the codesigning identity in the target build settings doesn't work either. While Apple claims in it's documentation that for App Store submission the signing identity has to be changed in the project build settings.
I run an archive build.
I select the archive in the organizer and click validate.
This error message appears:
"My Name" is a valid identity. However,
you do not have the associated package identity.
I can't find any pointer to what the term "package identity" actually means. What is most frustrating to me is that this terminology mess in Apples documentation concerning the code signing and submission process appears not very clear and precise to me. At least not as clear and precise as the documentation for the same process concerning iOS App submission (which is using completely different terminology).
Probably I understood something wrong? Thanx for any help or pointer in advance.
OK, I have some important pointers (additional to Apples documentation) for people stumbling over similar issues.
The error message is totally misleading.
Don't take every word in Apples documentation too seriously.
For solving the issue, 2 points have been most significant:
Additional to all the other profile-mess you need 2 certificates for submission to the Mac App Store (contrary to the same process for iOS App Store submission). Both have to be installed together with their corresponding public and private key pairs.
Mac App
Mac Installer
The codesigning needs to be set on the build target, not the project. I don't remember where but this was described wrong side around in one of Apples documentations.
Eventually my submission worked by keeping to those 2 points.
There is an additional issue with Keychain & XCode.
When Xcode uses a certificate, they want one and only one certificate in your keychain. If you have an expired one, as well as a valid one, Xcode often fails the operation.
So you look at your keychain using Keychain Access, and do not see an expired certificate. It is still there! The default setting for Keychain Access hides expired certificates. Goto the View menu and select Show Expired Certificates. Delete all the expired ones, they are not good for anything.
Quit Keychain Acces and Relaunch Xcode. Xcode often requires a relaunch when adding/deleting certificates.
At that point, the Archive Validate process worked for me.
This is what it was for me as well.
Just want to clarify, you absolutely need both Mac App Distribution and Mac Installer Distribution certificates. Thanks Jacque for your explanation above. It should look like this:
Yes the problem is Mac Installer Distribution certificate.
The easiest way to have everything fixed and loose all the troubles just go to Xcode->Window->Organizer->Devices and then on the lower right corner press on Refresh and log in with your account... xcode will generate and download all the certificates and provisioning profiles needed.

Beta-testing a Mac App Store app

I have an app that I'm going to put in the Mac App Store. I'd like to add iCloud support for preference syncing, and for that reason, I'd like to distribute the betas signed in such a way that they can access iCloud.
However, I haven't been able to find anything in the Mac documentation library about distributing an app, signed with a distribution key, outside of the App Store, and being able to access iCloud.
So far, my attempts to distribute such an application have met inability to launch on testers' machines, with messages in the Console complaining about the app having the iCloud entitlement.
Is what I'm after possible, or should I abandon iCloud support? If it is possible, what do I need to do to make a distributable, iCloud-capable build?
Edit: To be clear, you can replace “iCloud support” in this question with any other feature that is only available to App Store apps. I mention it to establish that the solution is not “just distribute it unsigned”. iCloud is the goal in my specific case; I'm asking about the general process.
You would need to gather the UUID for the tester's mac, either available via Xcode's Organizer or you can also access it via Apple System Profiler under the hardware overview. After adding it to the developer portal you'd generate a provisioning profile.
In order for them to actually run the application they would need to make use of an iTunes Connect test user account. This is one of two types of accounts that you can create in iTunes Connect, the other being an account with privileges (financial/technical/etc) for your developer membership. The test user account is needed in order for a receipt to be generated and the application actually run. Though you might be able to sidestep the test user account requirement by not actually validating receipts at that phase of development.
If you want to do iCloud or Push you need the UUID.
If you want to test a MAS app that doesn't need iCloud or Push, but does do receipt validation you need only the test user account.
My iCloud Mac app is stil in development, so I didn't try yet. But isn't it possible to sign the app with an entitlement and add a test user to iTC. In the OS X provisioning portal you can already add devices, and you need to add the testers Macs there and re-create the provisioning profile afterwards. After build & archive you "Share..." the app as installer or .app. The user needs to login with the/his test user you created in iTC on her/his Mac.

Resources