Introduction:
Distributing macOS applications outside of the App Store mandates a process called notarization, which ensures the security and integrity of the software. This involves several steps, including building, signing, and verifying the application’s authenticity with Apple. Notarization allows developers to distribute their apps outside the App Store ecosystem while maintaining user trust and security.
I will discuss how we can sign and notarize the macOS app developed on Electron.
Before start notarization, we need to create an app from the source code. To create the app we can use the electron-packager node module.
To install the electron-packager open the terminal and navigate to the project directory and run the below command.
This module requires Node.js 10.0 or higher to run.
npm install --save-dev electron-packager
After successful installation runs the below command to build the application. Click here for more details on electron packager.
electron-packager . <APP_NAME> --overwrite --platform darwin --arch x64 --out <path/to/.app>
It will take some time to build. After a successful build app will be created in the mentioned PATH. Now we need to sign the app.
To Sign and Notarize the app we need a valid and Active Apple Developer account for creating Developer ID Application Certificate, Provisioning profile, App Identifiers, and app-specific password.
Let’s check how we create those
For macOS Apps, we need to choose the Certificate type as “Developer ID Application” when creating the certificate on the Developer portal.
Click here to know the process to create a Developer Certificate, Provisioning profile, and Application Identifier on Apple Developer Portal.
After creating the Provisioning profile download the same which we need for App signing.
Now we need to create an App-Specific Password. Please follow the steps to create the same.
- Open the link https://appleid.apple.com/
- Sign in with your Apple ID and Password
- Go to the Security section and click on Generate Password under APP-SPECIFIC PASSWORDS
After generating the password that needs to be saved in the Local Items Keychain so that we can access the password securely during App notarization.
Run the below command to save the password to Keychain’s local items for XCODE 12 or earlier. For later versions click here.
xcrun altool --store-password-in-keychain-item "NOTARIZE_PASSWORD" -u "<APPLE_ID(Email)>" -p "<APP_SPECIFIC_PASSWORD>"
We are just a few steps away from app signing and notarization.
We need to create an Entitlements plist file which needs to for app signing. Create the plist file and add the below keys and values to the file.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<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.debugger</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
For signing the app we need to install electron-osx-sign node module.
Run the below command to install the module globally.
npm install -g electron-osx-sign
After successful installation, we need to run the below command to sign the application. Click here for more details on electron-osx-sign.
electron-osx-sign <path/to/.app> --provisioning-profile=<path/to/provisioning profile (Which Downloaded Earlier)> --entitlements="<path/to/entitlement plist file (Which Created Earlier)>" -- entitlements-inherit="<path/to/entitlement plist file (Which Created Earlier)>" -- identity="Developer ID Application: <APPLE_ID_OWNER_NAME>(<TEAM_ID>)" --platform=mas --hardenedRuntime=true
After successful signing, we need to check whether the signing is valid or not. To check run the below commands.
To check the binary is valid or not run
codesign -vvv — deep — strict <path/to/.app>
To check the binary is signed with a valid developer certificate or not run
spctl -vvv --assess --type exec <path/to/.app>
If all is good we can start the notarization process. To notarize the app we need to install a node module called electron-notarize. Run the below command to install the package globally.
npm install -g electron-notarize
Once the module is installed successfully we can run the below command for notarization. Click here for more details on electron-notarize.
electron-notarize --bundle-id "<APP_IDENTIFIER(Created Earlier on Developer Portal)>" --username "<APPLE_ID(Email)>" --password "<a href="http://twitter.com/keychain" target="_blank" rel="noreferrer noopener">@keychain</a>:NOTARIZE_PASSWORD" "<path/to/.app>"
If your Apple account has multiple teams, you need to pass the ascProvider name in the above command to specify the provider.
--ascProvider="<PROVIDER_SHORT_NAME>"
You can run the below command to know the list of providers of your apple account for XCODE 12 or earlier. For later versions click here.
xcrun altool --list-providers -u <APPLE_ID(Email)> -p "<a href="http://twitter.com/keychain" target="_blank" rel="noreferrer noopener">@keychain</a>:NOTARIZE_PASSWORD"
After the successful notarization process apple will provide the RequestUUID which we can use to check the status of the notarization. If error during notarization you can check possible issues from here.
To check the status run the below command
xcrun altool --notarization-info <RequestUUID> -p "<a href="http://twitter.com/keychain" target="_blank" rel="noreferrer noopener">@keychain</a>:NOTARIZE_PASSWORD"
If notarization is completed successfully then we can distribute our app outside the app store. To distribute we need to create the dmg file from the .app. To create dmg we need to install a node module named electron-installer-dmg.
Run the below command to install the module globally.
npm i electron-installer-dmg -g
Post successful installation we need to run the below command to create the dmg file.
electron-installer-dmg <path/to/.app> <appname>
After running the command a dmg file will be created in the directory and that we can distribute.
Conclusion
Distributing macOS apps outside the App Store requires notarization. This involves building the app, signing it with a Developer ID, creating entitlements, verifying the signing, and notarizing it through Apple. Once notarized, the app can be distributed, typically via a .dmg file