If you are building an app for the Mac platform, in order to allow other people to run your app on their own Mac without security warnings and issues you need to code sign and notarize your app. This article explains how to do this.
1. Prerequisites
Xcode 13 or higher is required to sign and notarize your app.
1.1. Apple ID 2FA
Two-Factor Authentication (2FA) must be enabled for your Apple ID in order to notarize apps.
You can do this in your Apple ID Account by clicking Account Security in the Sign-In and Security section.

1.2. App-Specific Password
An App-specific password is required in order to notarize apps.
You can create one in yourApple ID Account by clicking the Generate an app specific password button in the App-specific Passwords section of Sign-In and Security.

1.3. Developer ID
A Developer ID is required in order to notarize apps.
Certificates can be generated in your Apple Developer Account. Under Certificates, IDs & Profiles click Certificates then the blue plus icon to generate a new certificate.


The Developer ID Application certificate is required for signing the app for distribution outside of the Mac App Store.
After certificates have been generated they can be downloaded or generated in Xcode (recommended).
1.3.1. Download Certificates in Xcode (Optional)
To download the certificates in Xcode navigate to Xcode->Settings->Accounts
Click Manage Certificates then click + in the new window and select the certificate you want to download.
The certificate will be automatically added to the Keychain.


1.4. LC4FM Settings
Select Deployment Options for the LC4FM project you wish to deploy and notarize. Then click Edit.
1.4.1. Version Number
The Version field must be populated in the format 1.0.0
and must be incremented each time a new version of the app is deployed.
2. Deployment
Deploy the app by clicking Test & Deploy then Build app for distribution.
Ensure the App ID is populated in the form com.COMPANYNAME.APPNAME
.
3. Codesigning
To codesign an .app, a .pkg, or a .dmg you need your Developer ID certificates.
Signing .app and .dmg is done with the tool sign and the Developer ID Application certificate.
3.1. Creating Entitlements File
Certain entitlements are required by the app and must also be added using an entitlements.plist file.
Create this file by creating a blank file, using for example the TextEdit app, and setting the content to the following:
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.personal-information.location</key>
<true/>
<key>com.apple.security.personal-information.addressbook</key>
<true/>
<key>com.apple.security.personal-information.photos-library</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
</dict>
Finally save the file as entitlements.plist
.
3.2. Codesigning the App
To codesign the app the exact name of your Developer ID Application is required.
This can be found in Keychain Access if you generated the certificates using Xcode.
The line in keychain access should be in the form Developer ID Application: <your_name> (<your_team_id>)
this entire string is <your_developer_id>
.
Now run the following command in the terminal, replacing the <your_developer_id>
, <path_to_entitlements.plist_file>
, and <path_to_app>
with the ID which was found above, the path to the entitlements.plist file created in the previous step, and the path to the app deployed in step 2.
sudo codesign --verbose --deep --force --sign "<your_developer_id>" --options runtime --entitlements <path_to_entitlements.plist_file> <path_to_app>
If successful then the terminal should output something like:
signed app bundle with Mach -O universal (x86_64)
3.3. Verifying Signing (Optional)
You can verify that codesigning has succeeded using the following command:
codesign --verify --verbose "<path_to_app>"
Replacing <path_to_app>
with the path to your app file.
If successful then the terminal should output something like:
valid on disk
satisfies its Designated Requirement
4. Creating and Signing a DMG (Optional)
Mac applications can be distributed via a DMG, the next steps describe how to create the DMG and sign it.
4.1. Creating the DMG
The following command can be used to create a DMG:
hdiutil create -volname "<Name_of_Volume>" -srcfolder "<path_to_app>" -ov -format UDZO "<Name_of_DMG>"
Where <Name_of_Volume>
is the name you want your DMG to display when mounted, <path_to_app>
is the path to the signed app, and <Name_of_DMG>
is the filename of the DMG. (For example LCFM App.dmg)
If successful the terminal will display the path to the newly created DMG.
4.2. Codesigning the DMG
The DMG can now be codesigned using a command similar to the one used earlier to sign the app.
Again replace <your_developer_id>
with your developer ID found in the keychain, and <path_to_dmg>
with the path to the DMG you created in the previous step.
codesign --deep --force --verify --verbose --sign "<your_developer_id>" --options runtime "<path_to_dmg>"
4.3. Verify Signing (Optional)
You can verify that codesigning has succeeded using the following command:
codesign --verify --verbose "<path_to_dmg>"
Replacing <path_to_dmg>
with the path to your app file.
If successful then the terminal should output something like:
valid on disk
satisfies its Designated Requirement
5. Compress the App (Optional)
If you are not distributing your app via DMG then you must compress the app in order to upload it to Apple for notarisation.
Simply right-click the app and select Compress.
The ZIP file can now be uploaded to Apple for notarisation.
6. Notarizing the App or DMG
In order to notarise the app or DMG it must be uploaded to Apple. The app cannot be uploaded directly, only ZIP files, Installer Packages, and DMGs can be uploaded.
To submit the file to Apple's notarisation services you'll need the command line tool notarytool.
notarytool was introduced with Xcode 13 so older versions of Xcode cannot use this tool.
To submit to Apple you need to specify your Apple-ID, AppSpecificPassword and your DeveloperTeamID every time using the following command:
xcrun notarytool submit --apple-id "<your_AppleID>" --password "<your_AppSpecificPassword>" --team-id <your_team_id> --wait "<path_to_file>"
Here <your_AppleID>
is the AppleID you used to register for the Apple Developer Account, <your_AppSpecificPassword>
is the password created in step 1.2, <your_team_id>
is found in your Apple Developer Account under Membership Details, and <path_to_file>
is the path to the ZIP or DMG you wish to notarise.
The terminal should display something like:
Conducting pre-submission checks for app.zip and initiating connection to the Apple notary service...
Submission ID received
id: df02b221-e999-4222-9c7e-8436c4a3e93a0
Successfully uploaded file(12,0 MB of 12,0 MB)
id: df02b221-e999-4222-9c7e-846c4a3e93a0
path: /Users/daniel/lc/app.zip
Waiting for processing to complete.
Current status: Accepted........
Processing completd
id: df02b221-e999-4222-9c7e-846c4a3e93a0
status: Accepted
Notarisation may take some time to complete. According to Apple it is usually less than one hour.
7. Stapling the App or DMG
Stapling attaches the notarisation to the App or DMG so that it is available even when an internet connection is not available.
To staple use the following command:
xcrun stapler staple -v "<path_to_app>"
Where <path_to_app>
is the path to the app or DMG.
If successful the terminal should output something like:
The staple and validate action worked!
Your app is now signed and notarized and can be distributed outside of the Apple Mac store.